2010-02-18 5 views
7

considerar lo siguiente:¿Cómo se typedef o redefine una clase anidada con plantillas en la subclase?

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 
}; 

Cómo utilizar la clase anidada con plantilla en la clase derivada? ¿Es esto posible en la versión actual de C++ estándar?

+0

No entiendo por qué está haciendo Anidado una clase 'derivada', porque la clase derivada heredará la clase anidada de todos modos. – Craig

+0

Quiero la clase "anidada" encapsulada en "Base", y la clase "Derivada" puede extender o usar la clase "Base :: anidada". – leiiv

+0

¿En qué caso de uso '' que utiliza Base :: Anidado; 'no funciona? –

Respuesta

10

en realidad using funciona como se anuncia, simplemente no se deshace de la cuestión nombre dependiente de la plantilla y puede no constituyen actualmente las plantillas de alias directamente (será 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 
} 

Hay otra posible Gotcha cuando se utiliza Derived<T>::Nested en las plantillas, pero una vez más que es una cuestión nombre del dependiente, no relacionados con la herencia-:

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; 
} 

Sólo recuerde que los nombres que dependen de la plantilla argumentos tienen que ser

  • typename con el prefijo si es un tipo dependiente: typename A<T>::B
  • directamente con el prefijo template si es dependiente de una plantilla: A<T>::template f<int>()
  • tanto si ambos: typename A<T>::template B<int>
  • typename es ilegal en base-clase-listas: template<class T> struct A : B<T>, C<T>::template D<int> {};
+0

¿Puedes dar un ejemplo de cómo usar el tipo anidado para un miembro de datos de la clase derivada? Si todavía tenemos que usar 'Base ::', ¿sería inútil el 'que usa Base :: Nested'? – leiiv

+1

Haré. 'usando Base :: Anidado' no es inútil, se usa en' f() 'y' g() '- sin la declaración' using', tendrías que acceder a 'Nested' via' Base' in ' f() '. –

+0

Gracias gf, eso es muy útil. – leiiv

0

Prueba esto:

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; 
} 

Compilado fino utilizando gcc 4.3.3 en Slackware 13

+0

Lo siento, pero esto no es lo que estoy pidiendo. Lo que quiero saber es si es posible tipear o usar 'base pública :: plantilla Anidada ' dentro de la clase 'Derived', porque ese tipo se usará en muchos lugares. – leiiv

+0

Ok, lo siento, voy a tratar de encontrar una respuesta adecuada – coelhudo

0

todavía no estoy 100% seguro de lo que quiere, pero se podría tratar.
Este compilado en 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

esto también puede usar \t Derivada :: Anidados blah3; – Craig

+0

ah good ol 'VS .. g ++ 4.4.1 no me deja hacer eso ... – leiiv

+0

¿Cuál es la diferencia entre lo que hice y lo que hizo Craig? Realmente no vi:/ – coelhudo

2

Esto parece funcionar:
(EDIT:.! añaden algunos más líneas para mostrar la primera declaración de plantilla y gracias a Samir Talwar para corregir mi formato)

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

Pero ahora los usuarios siempre tienen que especificar un segundo argumento de plantilla para 'Derived'. –

+0

Sí, y uno derivado no puede tener más de un tipo de NestedDerived. Es una limitación seria, pero de lo contrario no veo ninguna manera de hacer que NestedDerived haga uso de Base :: Anidado. – Beta

Cuestiones relacionadas