2015-08-17 1 views
19

Avoir (bug possible?):modèle variable en classe modèle - erreur inattendue

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; } 
  • ne compile pas avec clang ++ 3.6.

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

  • Ne compile pas avec g ++ 5.2.

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


(1) ideone

Compile avec les deux clang ++ et g ++.

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

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

Pourquoi (0) ne parviennent pas à compiler?

Il semble que le problème se produit si le modèle de variable est accessible via un paramètre de modèle (dans ce cas, TValue). La définition d'un alias de type pour TValue ou l'utilisation du mot-clé typename ne résout pas le problème.

Que se passe-t-il ici?

+1

Qu'est-ce que 'template statique constexpr T valeur {0};' supposé faire? Est-ce quelque chose de nouveau? Comment cela s'appelle-t-il? –

+4

@ BЈовић, Il est appelé * modèle de variable *, ajouté en C++ 14. Voir [this] (https://en.wikipedia.org/wiki/C%2B%2B14#Variable_templates) (wiki) et [this] (http://fr.cppreference.com/w/cpp/language/variable_template) (cppreference) – Nawaz

+2

(0) échoue pour moi sur clang 3.6, avec "ne peut pas se référer au modèle variable" 'value' 'sans une liste d'arguments modèle" – Barry

Répondre

10

Il s'agit certainement d'un bogue gcc et clang dans le traitement des gabarits variables en tant que noms dépendants. J'ai soumis gcc 67248 et clang 24473.

Pour contourner le problème pour l'instant, les deux compilateurs soutiennent l'ancienne façon de faire des modèles variables, à savoir si vous avez ajouté:

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

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

alors les compiles suivants:

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

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

Je * savais * que c'était un bug. Étrange que gcc et clang se sont trompés, cependant. La solution de contournement que j'ai utilisée définissait en fait les fonctions 'static constexpr' qui enveloppaient les variables. –

0

J'ai eu quelques maux de tête avant lors de la création de fichiers d'en-tête de classe de modèle en C++.

Assurez-vous que l'implémentation de static constexpr T value{0}; se trouve dans le même fichier d'en-tête que la déclaration.

+1

Cela devrait être un commentaire plutôt qu'une réponse –

+1

Cela devrait être inclus comme un commentaire pas une réponse – gpullen

+0

Merci. C'était ma première réponse ... excuses :-) –