2013-04-08 1 views
22

En répondant à this SO question, j'ai trouvé dans le standard (déjà C++ 03, toujours en C++ 11) que vous ne pouvez utiliser des adresses que comme arguments de template non-type s'ils sont de le formulaire & id-expression (plus quelques exceptions). Mais je ne pouvais pas répondre pourquoi c'est le cas.pointeur en tant qu'argument de modèle non-type

14.3.2 Template arguments non de type [temp.arg.nontype]

Un modèle argument pour un non-type, le modèle à paramètres non-template est l'un de:

[...]

- une expression constante (5,19) qui désigne l'adresse d'un objet avec une mémoire statique> durée et la liaison externe ou interne ou une fonction de liaison externe ou interne, y compris les modèles de fonction et modèle de fonction -ids mais exc lissant les membres de classe non statiques, exprimés (en ignorant les parenthèses) & id-expression, sauf que le & peut être omis si le nom fait référence à une fonction ou un tableau et doit être omis si le paramètre de modèle correspondant est une référence; [...]

(n3485, moi qui souligne)

Exemple:

using TFoobar = int (*)(); 
template < TFoobar tp > struct foo_struct{}; 

int foobar() { return 42; } 
constexpr TFoobar pFoobar = &foobar; 

foo_struct < &foobar > o0; // fine 
foo_struct <pFoobar> o1; // ill-formed 

Je suppose qu'il a quelque chose à voir avec les phases de traduction, à savoir le compilateur ne sait pas grand-chose à propos des adresses. Pourtant, pourquoi n'est-ce pas autorisé? Ne devrait-il pas être possible pour le compilateur d'utiliser quelque chose de similaire à la substitution de macro pour remplacer pFoobar par &foobar?

+1

Très bonne question. –

+1

Je suppose qu'il s'agit de faire des changements conservateurs.C++ 11 est plein de manières très strictes pour que le langage fasse les choses afin de rendre les choses plus faciles pour les implémenteurs du compilateur. Il pourrait être possible d'étendre C++ 11 pour permettre ce qui précède, mais c'est une question pour C++ 14 ou au-delà! – Yakk

+0

[Il existe une proposition] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4268.html) pour supprimer ces restrictions. – dyp

Répondre

1

Envisagez les classes Foo<&X> et Foo<&Y>, les deux avec un membre statique int Bar. L'éditeur de liens doit être capable de dire si votre programme a 1 ou 2 objets Bar. Considérez maintenant que l'éditeur de liens est également la partie la plus susceptible d'attribuer des valeurs à &X et &Y.

Regardez à nouveau la norme. Comme il est écrit, le compilateur n'a pas besoin de communiquer l'adresse réelle à l'éditeur de liens. Au lieu de cela, il passe le id-expression. Les lieurs sont déjà tout à fait capables de déterminer si deux id-expression sont identiques, même avant de leur attribuer une adresse numérique.

+1

Je suis conscient qu'un substitut peut être utilisé à la place de l'adresse réelle. Mais comment cela répond-il à ma question pourquoi un objet 'constexpr' ne peut pas être utilisé comme argument de modèle de pointeur? – dyp

+0

Et, pour ajouter au commentaire DyP, si un pointeur constexpr à la fonction est fait, sa valeur peut être calculée et transmise à l'éditeur de liens ('& id' ou' nullptr') (et plus: cela ne contredit pas votre réponse). – Synxis

+0

@Synxis: Non, le compilateur ne peut pas calculer la valeur d'un pointeur (constexpr) à fonctionner, puisque l'éditeur de liens donnera son adresse à la fonction. – MSalters

0
  1. Il ne peut pas s'agir d'une variable, car les variables ne sont définies qu'à l'exécution.
  2. Il ne peut pas s'agir d'un constexpr, car la valeur d'une adresse ne peut pas être connue au moment de la compilation; dans la plupart des cas, il ne sera fixé qu'après la réinstallation avant l'exécution.
  3. Il pourrait théoriquement être une expression arithmétique (même si cela n'est pas autorisé dans la norme), mais dans le cas courant d'une adresse d'un élément de tableau, vous pouvez simplement utiliser &arr[i] au lieu de arr + i.
+0

Qu'est-ce qui ne peut pas être un constexpr? Une adresse de fonction est connue au moment de la compilation (y compris le temps de liaison). En outre, la relocalisation se produit principalement pour les bibliothèques partagées, sur les systèmes modernes, les «exe» ne sont souvent pas relocalisés. – Synxis

+0

Ad 3: Une expression constante _is_ est autorisée dans la norme si je l'interprète correctement; c'est juste interdit pour les fonctions (fonction ptrs). Bien que je puisse voir pourquoi une expression arithmétique n'a pas beaucoup de sens sur une fonction ptr, une expression constante évaluant une fonction ptr a du sens pour moi, voir l'exemple dans mon OP (ou la question originale de Synxis). – dyp

Questions connexes