2010-12-06 57 views
3

J'ai une application C++ Visual Studio 2008 où une classe de base A_Base doit instancier un membre de données dont le type est défini par une classe parente. Par exemple:classe de base utilisant un type défini par la classe parent

template< typename T > 
class A_Base 
{ 
public: 
    typedef typename T::Foo Bar; // line 10 

private: 
    Bar bar_; 
}; 

class A : public A_Base<A> 
{ 
public: 
    typedef int Foo; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    A a; 
return 0; 
} 

Malheureusement, il semble que le compilateur ne sait pas ce que T::Foo est jusqu'à ce qu'il soit trop tard et je reçois des erreurs comme ceci:

1>MyApp.cpp(10) : error C2039: 'Foo' : is not a member of 'A' 
1>  MyApp.cpp(13) : see declaration of 'A' 
1>  MyApp.cpp(14) : see reference to class template instantiation 'A_Base<T>' being compiled 
1>  with 
1>  [ 
1>   T=A 
1>  ] 
1>MyApp.cpp(10) : error C2146: syntax error : missing ';' before identifier 'Bar' 
1>MyApp.cpp(10) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 
1>MyApp.cpp(10) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 

Est-il possible de réaliser ce type de fonctionnalité?

Merci, paulh

Répondre

3

Vous pouvez essayer ce qui suit:

template< typename T > 
class A_Base 
{ 
public: 
    typedef typename T::Foo Bar; // line 10 

private: 
    Bar bar_; 
}; 

class A_Policy 
{ 
public: 
    typedef int Foo; 
}; 

class A : public A_Base<A_Policy> 
{}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    A a; 
return 0; 
} 
5

A_Base<A> est instancié à un point où A n'est pas encore terminée:

class A : public A_Base<A> 

Vous pouvez envisager d'utiliser un Classe de traits:

template<class T> struct traits; 

template< typename T > 
class A_Base 
{ 
public: 
    typedef typename traits<T>::Foo Bar; // line 10 

private: 
    Bar bar_; 
}; 

class A; // Forward declare A 

template<> // Specialize traits class for A 
struct traits<A> 
{ 
    typedef int Foo; 
}; 

class A : public A_Base<A> {}; 

int main() 
{ 
    A a; 
} 
1

La classe A dépend de la classe qui dépend de la classe A ... etc Vous avez une récursivité ici. Vous devez déclarer Foo dans une classe distincte.

class A; 

template<typename T> struct Foo; 
template<> struct Foo<A> { typedef int type; }; 

template< typename T > 
class A_Base 
{ 
public: 
    typedef typename Foo<T>::type Bar; // line 10 

private: 
    Bar bar_; 
}; 

class A : public A_Base<A> 
{ 
}; 

Voir également GotW #79.