2012-01-23 1 views
3

Si je tente d'appeler une fonction membre d'un membre de la classe de base d'une classe de modèle à l'autre bout de la hiérarchie d'héritage,classe dérivée héritant sans canevas par classe CRTP, l'accès à un membre du groupe de base objet

class memberobj {public: void bar(){}}; 

class basis {public: memberobj foo;}; 

template<class Base, class Derived> 
class crtp : public Base { /* ... */ }; 

template<class Option> 
class choice : crtp< basis, choice<Option> > { 
    using basis::foo; 
public: 
    void test() {foo.bar();} 
}; 

class someoption {}; 

int main() { 
    choice<someoption> baz; 
    baz.test(); 
    return 0; 
} 

Je reçois ce message d'erreur:

g++-4.6 -o bin/crtptest crtptest.cpp 
crtptest.cpp: In member function ‘void choice<Option>::test()’: 
crtptest.cpp:12:21: error: ‘class basis’ has no member named ‘bar’ 
make: *** [bin/crtptest] Error 1 

si bar est évidemment un membre de un membre debasis, pas de basis lui-même.
Cela ne se produit pas avec les classes finales non-template (dont un nombre est déjà utilisé, toutes dépendant de la classe intermédiaire crtp, donc je ne voudrais rien changer à ce sujet), ni avec une classe de template qui dérive directement à partir de basis.

Quel est le problème ici?

+0

La directive à l'aide n'est pas nécessaire. – AJG85

+0

@ AJG85 En fait j'utilise l'héritage protégé dans le problème réel, mais il a produit la même erreur que cet exemple. – leftaroundabout

+0

Vous pouvez utiliser un 'typedef' comme décrit ci-dessous pour former correctement la directive using pour la classe de base correcte, mais cela ne devrait pas être nécessaire sauf s'il s'agit d'un héritage privé. – AJG85

Répondre

3

Vous le faites fausse route:

using basis::foo; //wrong way 

Qu'est-ce que basis? Ce n'est pas la classe de base de choice. Vous devriez faire ceci:

typedef crtp< basis, choice<Option> > base; 
using base::basis::foo; 

Parce que crtp< basis, choice<Option> > est la base de choice classe et foo devient membre de choicepar sa classe de base. Donc, il y a une différence subtile.

Maintenant, il fonctionne: http://ideone.com/RPnyZ

+1

Mais alors, que signifie «using basis :: foo»? (Puisque ce n'est pas une erreur, cela doit signifier quelque chose, non?) –

+0

Je pensais que ce n'était pas nécessaire parce que s'il y a une classe intermédiaire qui n'est pas un modèle, vous pouvez simplement faire 'using base :: foo;' au lieu de ' en utilisant intermediate :: base :: foo; ', mais apparemment pas avec un template de classe intermédiaire. – leftaroundabout

+1

@MagnusHoff: Cela ne veut rien dire. Le compilateur devient confus. – Nawaz

Questions connexes