En passant const char* comme argument de modèle
Pourquoi ne pouvez pas vous passer des chaînes de caractères littérales ici? J'ai fait le travail avec une très légère solution de contournement.
template<const char* ptr> struct lols {
lols() : i(ptr) {}
std::string i;
};
class file {
public:
static const char arg[];
};
decltype(file::arg) file::arg = __FILE__;
//Getting the right type declaration for this was irritating, so I C++0xed it.
int main() {
//lols<__FILE__> hi;
//Error: A template argument may not reference a non-external entity
lols<file::arg> hi; //Perfectly legal
std::cout << hi.i;
std::cin.ignore();
std::cin.get();
}
const char file::arg[] = __FILE__;
Cela devrait vous permettre de redescendre à C++03 :).- J'ai essayé aussi. Compilateur a jeté erreur.
- Impair. g++ compile très bien (avec -pédant).
- Irritant, j'ai toujours pensé que c'était impossible. Maintenant que je l'ai, je n'arrive pas à lui faire faire quelque chose d'intéressant ou d'utile.
- Qu'en essayant const char *const ptr pour l'argument de modèle à la place? Après tout, c'est un littéral.
- Noter que si, à portée espace de noms, vous aurez besoin
extern const char arg[] = __FILE__;
de donner la matrice de liaison externe (const objets ont une liaison interne par défaut). - Pour ceux qui sont intéressés, David a écrit, comment le faire ici — cpp-next.com/archive/2012/10/...
Vous devez vous connecter pour publier un commentaire.
Parce que ce ne serait pas un utilitaire utile. Depuis qu'ils ne sont pas autorisés forme d'un argument de modèle, il ne fonctionne pas.
Supposons qu'ils travaillent. Parce qu'ils ne sont pas tenus d'avoir la même adresse pour la même valeur, vous obtiendrez les différentes instanciations même si vous avez le même littéral de chaîne de valeur dans votre code.
Vous pourriez écrire un plugin pour votre éditeur de texte qui remplace une chaîne de caractères en une liste séparée par des virgules de chaînes de caractères et à l'arrière. Avec variadic templates, vous pourrait "résoudre" le problème de cette façon, d'une certaine façon.
extern
est ici nécessaire. Si le littéral de chaîne est définie commestatic const char * foo = "foo";
et il est utilisé uniquement à l'intérieur de la même module, pourquoi ne pas l'utiliser comme un modèle de valeur de l'argument, étant donné que le modèle résultant de l'instance ne peut être utilisé à l'intérieur du module? Pourquoifoo
pas une constante de compilation? Ne fait pas de sens pour moi que ce soit. Aussi les commentaires sur le fait que c'est "utile" ne parviennent pas à me convaincre. Il peut être utile dans certains scénarios.__LINE__
comme son modèle. Je ne veux pas qu'il soit la copie constructible ou quoi que ce soit, j'ai juste besoin d'un moyen d'ajouter une corde à mon exceptions sans réellement la construction d'une chaîne de caractères à chaque case.C'est possible, mais l'argument de modèle doit avoir une liaison externe, ce qui empêche l'utilisation des chaînes de caractères littérales et atténue l'utilité de le faire.
Un exemple que j'ai est:
namespace std
C'est comment je le fais. Fait beaucoup plus de sens pour moi:
Cela fonctionne pour les classes et, de l'OMI, est utile. La mise en œuvre est rapide et sale, mais peut être facilement fait en nettoyant:
De sortie:
Vrai!
Faux!
Vrai!
Faux!
Bonne question, j'ai pensé jeter mon chapeau dans l'anneau... je pense que vous pouvez passer des pointeurs vers des variables statiques non-gabarit de type d'arguments. À partir de C++20 on dirait qu'il ne sera pas un problème... Jusqu'à alors, voici quelques bon marché macro pour le faire fonctionner.