Ich versuche, Bedeutung und Auswirkungen von 14.5.5/8 of the C++11 standard (idem in C++14 und ich nehme an, in C++ 17) zu versteheng ++ und Klirren ++ unterschiedliche Verhalten mit nicht-Typ Argumente in struct/class Spezialisierung
Der Typ eines Template-Parameters, der einem spezialisierten Nicht-Typ-Argument entspricht, darf nicht von einem Parameter der Spezialisierung abhängig sein.
und wie üblich zu verstehen, wer zwischen g ++ und clang ++ korrekt ist.
Der Standard anzeigen das folgende Beispiel
template <class T, T t> struct C {};
template <class T> struct C<T, 1>; // error
und beide g ++ ++ und Klappern give Fehler.
So weit, so gut.
Lassen Sie uns ein wenig erschweren das Beispiel eine Art Zugabe
template <typename, typename T, T>
struct foo { };
template <typename T>
struct foo<T, int, 1> { }; // compile
template <typename T>
struct foo<T, T, 1> { }; // error
Sowohl g ++ und Klirren ++ die erste Teil-Spezialisierung kompilieren (die Art der 1
, int
, ist kein Parameter der Spezialisierung) und geben Fehler mit der zweite (der Typ 1
ist T
, ein Parameter der Spezialisierung)
So weit, so gut.
Lassen Sie uns eine Vorlage struct bar
mit einem internen Typ vorstellen, dass hängt nicht von der Template-Parameter
template <typename>
struct bar
{ using type = int; };
und dem folgenden Programm
template <typename>
struct bar { using type = int; };
template <typename, typename T, T>
struct foo { };
template <typename T>
struct foo<T, typename bar<T>::type, 1> { };
int main()
{ }
es ohne Fehler durch g kompiliert ++ (versucht in Wandbox mit 4.9.3, 5.5.0, 7.2.0 und Kopf 8.0.0, mit C++ 11, C++ 14 und, wenn verfügbar, C++ 17) aber Clang ++ (3.9.1, 4.0. 1, 5.0.0, Kopf 6.0.0; C++ 11, C++ 14, C++ 17) geben das folgende an Fehler
prog.cc:11:38: error: non-type template argument specializes a template parameter with dependent type 'T'
struct foo<T, typename bar<T>::type, 1> { };
^
prog.cc:7:34: note: template parameter is declared here
template <typename, typename T, T>
~^
Wie immer: Wer hat Recht?
Klirren ++, die 1
abhängig von T
betrachten (wenn typename bar<T>::type
als int
fest) oder g ++, dass diese Abhängigkeiten nicht entbindet?
Der Vollständigkeit halber muss ich sagen, dass bar
Wechsel als
T
, nichts ändern
template <typename T>
struct bar { using type = T; };
so macht die bar<T>::type
abhängig folgt: g ++ kompiliert ohne Fehler und Klirren ++ den gleichen Fehler geben.