C ++ 98/03 qualificateur de collapsing et cv

Le code ci-dessous est compilé (gcc 4.7.2 ou icc 13) et produit une sortie “1 2”. Ce qui signifie que le qualificatif est supprimé, c’est-à-dire que f a le type de paramètre int& .

Pourquoi ça se passe? Si je comprends bien, selon §14.3.1.4:

Si un template-argument pour un template-paramètre T nomme un type “référence à cv1 S “, une tentative de création du type “référence à cv2 T ” crée le type “référence à cv12 S “, cv12 étant l’union du cv-quali fi cateurs cv1 et cv2 . Les quali fi cateurs cv redondants sont ignorés.

const ne doit pas être abandonné. Voici le code:

 #include  using namespace std; template  void f(const T& t) { t++; } int main() { int a = 1; cout << a; f(a); cout << ' ' << a << endl; return 0; } 

GCC 4.7.2 ne le comstack pas lorsque l’indicateur -std=c++98 est spécifié. En fait, en C ++ 98 (ainsi qu’en C ++ 03), les références aux références ne sont pas réduites.

Une tentative d’instanciation de f , où T = int& , produit la signature de fonction suivante (ici, je change intentionnellement la position du type d’argument T et du spécificateur const , ce qui est autorisé car const T& est identique à T const& ):

 void f(int& const& t) // ERROR: reference to reference is illegal 

Ce qui précède n’est pas légal en C ++ 98, ni en C ++ 03. C’est systématiquement l’erreur que vous obtenez de GCC 4.7.2:

 Compilation finished with errors: source.cpp: In function 'int main()': source.cpp:15:14: error: no matching function for call to 'f(int&)' source.cpp:15:14: note: candidate is: source.cpp:5:6: note: template void f(const T&) source.cpp:5:6: note: template argument deduction/substitution failed: source.cpp: In substitution of 'template void f(const T&) [with T = int&]': source.cpp:15:14: required from here source.cpp:5:6: error: forming reference to reference type 'int&' 

Néanmoins, si vous utilisez l’ -std=c++11 , le compilateur effectue un regroupement des références lors de l’instanciation du modèle: une référence lvalue à une référence lvalue devient une référence lvalue:

 void f(int& const& t) == void f(int& t) 

Ici, le qualificatif const est supprimé, car il s’applique à la référence et non à l’object référencé. Puisque les références ne peuvent pas être réaffectées, elles sont par nature const , raison pour laquelle le const est considéré comme superflu et supprimé. Voir ce Q & A sur SO pour une explication.

Cela donne une référence lvalue à une référence lvalue, qui se résout en une simple référence lvalue. Par conséquent, la signature du côté droit est instanciée.

Ce qui précède est un candidat viable pour résoudre l’appel de f(a) . Par conséquent, il comstack sans erreurs.

Voici 1770 où la citation en question semble provenir:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1770.html

14.3.1 – Arguments de type modèle

-4- Si un template-argument pour un template-paramètre T nomme un type “lvalue-reference to cv1 S”, une tentative de création du type “(lvalue ou rvalue) reference to cv2 T” crée le type “lvalue-reference à cv12 S, “où cv12 est l’union des qualificatifs cv1 et cv2. Si l’argument modèle nomme un type “rvalue-reference to cv1 S”, une tentative de création du type “lvalue-reference to cv2 T” crée le type “lvalue-reference to cv12 S.”. Si l’argument modèle nomme un type “rvalue-reference to cv1 S”, une tentative de création du type “rvalue-reference to cv2 T” crée le type “rvalue-reference to cv12 S.”. Les qualificatifs CV redondants sont ignorés.

Voici 2118 où la citation a été supprimée:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html

14.3.1 – Arguments de type modèle

-4- Si un template-argument pour un template-paramètre T nomme un type “reference to cv1 S” qui est une référence à un type A, une tentative de création du type “reference to cv2 T” “lvalue-reference to cv T “crée le type ” référence à cv12 S “, où cv12 est l’union des qualificatifs cv1 et cv2. Les qualificatifs cv redondants ne sont pas pris en compte “lvalue-reference to A”, tandis qu’une tentative de création du type “rvalue-reference to cv T” crée le type T.

Ce que vous citez semble être une formulation obsolète.