2010-02-18 8 views
7

Considérez ce qui suit:Comment typedef ou redéfinir une classe imbriquée modèle dans la sous-classe?

template <typename T> 
class Base { 
    public: 
    template <typename U> 
    class Nested { }; 
}; 

template <typename T> 
class Derived : public Base<T> { 
    public: 
    //How do we typedef of redefine Base<T>::Nested? 
    using Base<T>::Nested; //This does not work 
    using Base<T>::template<typename U> Nested; //Cannot do this either 
    typedef typename Base<T>::template<typename U> Nested Nested; //Nope.. 

    //now we want to use the Nested class here 
    template <typename U> 
    Class NestedDerived : public Nested { }; 

    //or like this: 
    Nested<int> nestedVar; // obviously does not work 
}; 

Comment utiliser la classe imbriquée dans la classe basé sur un modèle dérivé? Est-ce possible de faire dans la version actuelle de la norme C++?

+0

Je ne comprends pas pourquoi vous faites Imbriqué une classe 'dérivée', car la classe dérivée héritera de toute façon de la classe imbriquée. – Craig

+0

Je veux que la classe "imbriquée" soit encapsulée dans "Base", et que la classe "Derived" puisse étendre ou utiliser la classe "Base :: Nested". – leiiv

+0

Dans quel cas l'utilisation de Base :: Nested; 'ne fonctionne pas? –

Répondre

10

en fait using fonctionne comme prévu, il ne comprend tout simplement pas se débarrasser de la question dépendant du nom dans le modèle et il ne peut pas actuellement des modèles d'alias directement (sera fixed in C++0x):

template <class T> 
struct Base { 
    template <class U> struct Nested {}; 
}; 

template <class T> 
struct Derived : Base<T> { 
    using Base<T>::Nested; 

    // need to prefix Nested with template because 
    // it is a dependent template: 
    struct X : Base<T>::template Nested<int> {}; 

    // same here: 
    template<class U> 
    struct Y : Base<T>::template Nested<U> {}; 

    // data member, typename is needed here: 
    typename Base<T>::template Nested<int> data; 
}; 

void f() { 
    Derived<int>::Nested<int> n; // works fine outside 
} 

Il y a un autre possible Gotcha lors de l'utilisation Derived<T>::Nested dans les modèles, mais encore une fois ce qui est une question dépendant du nom, pas l'héritage liés:

template<class T> 
void g() { 
    // Nested is a dependent type and a dependent template, thus 
    // we need 'typename' and 'template': 
    typedef typename Derived<T>::template Nested<int> NestedInt; 
} 

Rappelez-vous simplement que les noms qui dépendent du modèle arguments doivent être

  • préfixé avec typename si son type à charge: typename A<T>::B
  • directement PREFIXÉ template si son modèle dépendant: A<T>::template f<int>()
  • les deux si les deux: typename A<T>::template B<int>
  • typename est illégal dans les listes de classe-base: template<class T> struct A : B<T>, C<T>::template D<int> {};
+0

Pouvez-vous donner un exemple d'utilisation du type imbriqué pour un membre de données de la classe Derived? Si nous devons encore utiliser 'Base ::', alors l'utilisation de 'Base :: Nested' serait-elle inutile? – leiiv

+1

Fera. 'using Base :: Nested' n'est pas inutile, il est utilisé dans' f() 'et' g() '- sans la déclaration' using', vous devrez accéder 'Nested' via' Base' dans ' f() '. –

+0

Merci beaucoup, c'est très utile. – leiiv

0

Essayez ceci:

template <typename T> 
class Base { 
    public: 
    template <typename U> 
    class Nested { }; 
}; 

template <typename T> 
class Derived : public Base<T> { 
    public: 
    //How do we typedef of redefine Base<T>::Nested? 
    //using Base<T>::Nested; //This does not work 
    //using Base<T>::template<typename U> Nested; //Cannot do this either 
    //typedef typename Base<T>::template<typename U> Nested Nested; //Nope.. 

    //now we want to use the Nested class here 
    template <typename U> 
    class NestedDerived : public Base<T>::template Nested<U> { }; 
}; 

int main() 
{ 
    Base<int>::Nested<double> nested; 

    Derived<int>::NestedDerived<double> nested_derived; 

    return 0; 
} 

Compilé fine en utilisant 4.3.3 gcc sur Slackware 13

+0

Désolé, mais ce n'est pas ce que je demande. Ce que je veux savoir, c'est, est-il possible de typedef ou en utilisant le 'base publique :: template imbriqué ' dans la classe 'Derived', parce que ce type sera utilisé dans beaucoup d'endroits. – leiiv

+0

Ok, désolé, je vais essayer de trouver une réponse appropriée – coelhudo

0

Je ne suis toujours pas 100% sûr de ce que vous voulez, mais vous pouvez essayer.
Cette compilation sur Visual Studio

template <typename T> 
class Base { 
    public: 
    template <typename U> 
    class Nested { }; 
}; 

template <typename T> 
class Derived : public Base<T> { 
    public: 
    //now we want to use the Nested class here 
    template <typename U> 
    class NestedDerived : public Nested<U> { }; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
Base<int>::Nested<double> blah2; 
Derived<int>::NestedDerived<int> blah; 

return 0; 
} 
+0

cela peut également utiliser \t Dérivé :: imbriqué blah3; – Craig

+0

ah bon ol 'VS .. g ++ 4.4.1 ne me laisse pas faire ça .. – leiiv

+0

Quelle est la différence entre ce que j'ai fait et ce que Craig a fait? Je n'ai vraiment pas remarqué:/ – coelhudo

2

Cela semble fonctionner:
(EDIT:.! Ajout de quelques lignes pour montrer la première déclaration de modèle et grâce à Samir Talwar pour corriger ma mise en forme)

template <typename T, typename U> 
class Derived : public Base<T> { 
    public: 
    typedef typename Base<T>::template Nested<U> Nested; 

    class NestedDerived : public Nested { }; 

    Nested nestedVar; 
}; 
+0

Mais maintenant les utilisateurs doivent toujours spécifier un deuxième argument de modèle pour 'Derived'. –

+0

Oui, et un dérivé ne peut pas avoir plus d'un type de NestedDerived. C'est une limitation sérieuse, mais sinon, je ne vois pas comment NestedDerived pourrait utiliser Base :: Nested. – Beta

Questions connexes