2012-05-17 4 views
4

Dans la configuration suivante, comment puis-je faire en sorte que je puisse me référer au nom Bar à l'intérieur de la classe dérivée Derived<T>? J'ai essayé using Foo<T>::Bar; J'ai essayé using Foo<T>::Bar;, mais cela n'aide pas. Y at-il une sorte de déclaration using qui peut rendre le nom d'un modèle de base imbriqué connu de la classe dérivée, de sorte que je peux garder le ­ cla ­ ration Bar<int> x?Comment nommer un modèle imbriqué dans une classe de base modèle?

Je sais que je peux dire typename Foo<T>::template Bar<int> x;, mais j'ai beaucoup de ces cas et je ne veux pas alourdir inutilement le code avec tant de verbosité. J'ai aussi beaucoup de "int s" distincts, donc un typedef pour chaque instance de modèle imbriqué n'est pas réalisable non plus.

Aussi, je ne peux pas utiliser GCC 4.7 à ce stade ni C++ 11, et aimerais donc une solution "traditionnelle" sans alias de template.

Répondre

6

En C++ 11 vous pouvez utiliser un modèle d'alias:

template <typename T> struct Derived : Foo<T> 
{ 
    template<typename X> using Bar = typename Foo<T>::template Bar<X>; 
    Bar<int> x; 
}; 

Modifier

La solution traditionnelle est ce que vous avez déjà dit, typename Foo<T>:template Bar<int>, ou de simuler un « typedef modèle "

template <typename T> struct Derived : Foo<T> 
{ 
    template<typename X> 
    struct Bar 
    { typedef typename Foo<T>::template Bar<X> type; }; 
    typename Bar<int>::type x; 
}; 

l'une des raisons pour ajouter des modèles d'alias à la langue est qu'ils soutiennent ce qui ne peut pas être exprimé facilement en C++ 03.

+0

Oui, c'est vrai. Malheureusement, je n'ai pas d'accès pratique à un tel compilateur, donc je voudrais une solution "traditionnelle" si possible: -S –

+0

@KerrekSB: Qu'est-ce qui est "non traditionnel" à ce sujet? – Nawaz

+0

@Nawaz: Je ne peux pas l'utiliser dans le projet où j'en ai besoin :-) –

1

Déclarer x comme Foo<T>::Bar<int> x; fonctionne simplement pour moi.

+0

Je pense que cela ne devrait pas marcher! Si c'est le cas, alors je me demande comment ça se fait. Peut-être, le compilateur a un bug? – Nawaz

+0

@Nawaz: Pourquoi? Il compile dans Dev-C++ 4.9.9.2. – miloszmaki

+0

Je ne veux pas changer les déclarations. Je * veux * vraiment pouvoir dire juste 'Bar x;'. –

0

Cela fonctionne:

template <typename T> struct Foo 
{ 
    template <typename U> struct Bar { }; 
}; 

template <typename T> struct Derived : Foo<T> 
{ 
    template<class W> 
    struct Bar : public Foo<T>::template Bar<W> { 

    }; 

    Bar<int> x; 
}; 

IDK si c'est ce que vous cherchez, mais il ne compile.

+1

Ce n'est pas exactement la même chose. C'est proche, mais même des choses triviales qui devraient fonctionner si les types étaient les mêmes ne sont pas dans ce cas: 'Derived d; Foo :: Barre y; ré.x = y; ' – cvoinescu

+0

Cela donne une syntaxe plus agréable que le« template typedef »dans ma réponse, mais il vaut la peine de noter que« Foo :: Bar »et« Derived :: Bar »ne sont pas réellement le même type. Cela n'a peut-être pas d'importance, mais cela pourrait être le cas dans certains cas, par ex. les modèles ou les surcharges qui fonctionnent avec 'Foo :: Bar' peuvent ne pas correspondre à Derived :: Bar' et donc la surcharge est utilisée. (Edit: Je vois cvoinescu dit la même chose, mais plus clairement.) –

+0

@cvoinescu Oui, cela ne fonctionne pas dans ce cas. Cependant, si la classe est utilisée uniquement en interne dans Derived, elle fonctionnera (bien que je ne sache pas si c'est le cas). Je voulais juste signaler une syntaxe plus courte que celle utilisée pour déclarer un template typedef. – mfontanini

Questions connexes