2015-08-17 7 views
19

Mit (mögliche Fehler?):Variable Vorlage in Template-Klasse - unerwarteter Fehler

struct Value 
{ 
    template<class T> 
    static constexpr T value{0}; 
}; 

(0) ideone

template<typename TValue> 
struct Something 
{ 
    void x() 
    { 
     static_assert(TValue::template value<int> == 0, ""); 
    } 
}; 

int main() { Something<Value>{}.x(); return 0; } 
  • funktioniert nicht mit Klirren kompilieren ++ 3.6.

    error: cannot refer to variable template 'value' without a template argument list

  • Kompiliert nicht mit g ++ 5.2.

    error: ‘template constexpr const T Value::value’ is not a function template


(1) ideone

Kompiliert sowohl mit Klappern ++ ++ und g.

struct Something 
{ 
    void x() 
    { 
     static_assert(Value::template value<int> == 0, ""); 
    } 
}; 

int main() { Something{}.x(); return 0; } 

Warum (0) nicht kompiliert?

Es scheint, dass das Problem auftritt, wenn auf die Variable Vorlage über einen Vorlagenparameter zugegriffen wird (in diesem Fall TValue). Wenn Sie einen Typalias für TValue definieren oder das Schlüsselwort typename verwenden, wird das Problem nicht behoben.

Was geht hier vor?

+1

Was ist 'Vorlage Statischer consExpr T-Wert {0}; soll es tun? Ist es etwas Neues? Wie heißt das? –

+4

@ BЈовић, Es heißt * variable Vorlage *, in C++ 14 hinzugefügt. Siehe [this] (https://en.wikipedia.org/wiki/C%2B%2B14#Variable_templates) (wiki) und [this] (http://en.cppreference.com/w/cpp/language/variable_template) (cppreference) – Nawaz

+2

(0) scheitert für mich am 3.6, mit "kann nicht auf variable template '' value'' ohne eine template argument list " – Barry

Antwort

10

Dies ist definitiv ein GCC und Clang Bug in ihrer Behandlung von variablen Vorlagen als abhängige Namen. Ich habe gcc 67248 und clang 24473 eingereicht.

Als Abhilfe für jetzt unterstützen beide Compiler auf die alte Weise variable Vorlagen zu tun, nämlich, wenn Sie hinzugefügt:

struct Value 
{ 
    template<class T> 
    static constexpr T value = 0; 

    template <typename T> 
    struct variable_template_ish { 
     static constexpr T value = Value::value<T>; 
    }; 
}; 

dann folgende compiliert:

template<typename TValue> 
struct Something 
{ 
    void foo() { 
     static_assert(TValue::template variable_template_ish<int>::value == 0, ""); 
    } 
}; 

int main() { 
    Something<Value>{}.foo(); 
} 
+1

Ich * wusste * es war ein Fehler. Seltsam, dass sowohl GCC als auch Clang es falsch verstanden haben. Die Problemumgehung, die ich verwendete, definierte 'statische conexpr'-Funktionen, die die Variablen umschlossen. –

0

ich einige gehabt haben Kopfschmerzen vor beim Erstellen von Vorlage Klassenheader-Dateien in C++.

Stellen Sie sicher, dass die Implementierung von static constexpr T value{0}; in der gleichen Header-Datei wie die Deklaration ist.

+1

Dies sollte ein Kommentar sein, anstatt eine Antwort –

+1

Dies sollte als Kommentar keine Antwort enthalten – gpullen

+0

Vielen Dank. Es war meine erste Antwort ... Entschuldigung :-) –