2012-10-12 2 views
4

Pourquoi suis-jeRéférence non autorisée à un membre non statique ... typedef?

Erreur C2597: référence illégale à un membre non statique 'derived<<unnamed-symbol>>::T'

lorsque je tente de compiler ce code dans Visual C++ 2010 64 bits? (Il semble bien sur x86 ... que l'on est correct?)

struct base { typedef int T; }; 

template<class> 
struct derived : base 
{ 
    using base::T; 
    derived(T = T()) { } 
}; 

int main() 
{ 
    derived<int>(); 
    return 0; 
} 
+0

Je ne parvient pas à reproduire le problème avec x64 MSVC 11.0 –

+2

Je reçois la même erreur sur VS2010 x86 également. Semble que le problème est la valeur par défaut 'T()'. Si vous modifiez l'instanciation en 'dérivé (0);' il compile. Aucune idée de ce que le hoquet est bien. – Praetorian

+1

Ne devrait-il pas s'agir du modèle ou du modèle ? – Recker

Répondre

3

Comme le commentaire de prétorienne mentionne, le problème est avec la valeur par défaut T(). Basé sur les détails d'erreur, using base::T confond apparemment le compilateur dans la recherche de T() comme un appel à la fonction de membre non statique de base plutôt que la construction d'une instance de type T.

Voici une correction intéressante qui fonctionne dans MSVC 2005 x86 (je n'ai pas essayé d'autres compilateurs). Notez que T() est préservé. Ceci désambiguise using base::T ou force simplement T à référencer le type hérité et non le using (qui ne sont apparemment pas la même chose pour le compilateur).

//... 
template<class> 
struct derived : base 
{ 
    using base::T; 
    derived(T = static_cast<T>(T())) { } //No error 
}; 
//... 

Edit: Essayez de changer base à cela et voir ce que les messages d'erreur que vous obtenez:

struct base { struct T{T(){}}; }; 

je reçois le C2597 original, mais aussi ceci:

erreur C2440: 'argument par défaut': impossible de convertir de '' à 'base :: T' Aucun constructeur pourrait prendre le type de source, ou la résolution de surcharge du constructeur était ambigu

Je ne sais pas ce que le compilateur signifie par '' là, mais il est probablement un problème similaire avec la définition originale de base. Cela compile bien si je supprime la ligne using base::T;.

+0

Whoa c'est ... bizarre. :) +1 belle réponse. – Mehrdad

0

Pourquoi vous utilisez using base::T? Les types définis dans la classe de base seront automatiquement disponibles dans la classe dérivée.

struct base { typedef int T; }; 
template< class X > 
struct derived : base {}; 
derived<int>::T v = 0; // this is OK in C++ 
+0

J'utilisais 'base :: T' parce que le code original était beaucoup plus compliqué (templates, etc.) et le compilateur se plaignait qu'il ne pouvait pas trouver' T' si je ne lui donnais pas l'indice 'using'. – Mehrdad

+0

Donc, si c'est vous pouvez le 'typedef', comme toutes les implémentations de STL. utilisez 'typedef base :: T T' et cela devrait fonctionner avec tous les compilateurs !! – BigBoss

0

Utilisez ce lieu (devrait être explicite):

template<class T> 
struct derived : base 
{ 
    derived(T = T()) { } 
}; 
Questions connexes