Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do we typedef or redefine a templated nested class in the subclass?

Tags:

c++

templates

Consider the following:

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

How to use the templated Nested class in the Derived class? Is this possible to do in current version of C++ standard?

like image 429
leiiv Avatar asked Feb 18 '10 01:02

leiiv


2 Answers

Actually using works as advertised, it just doesn't get rid of the dependent-name issue in the template and it can't currently alias templates directly (will be 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
}

There is another possible gotcha when using Derived<T>::Nested in templates, but again that is a dependent-name issue, not inheritance-related:

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

Just remember that names that depend on template arguments have to be

  • prefixed with typename if its a dependent type: typename A<T>::B
  • directly prefixed with template if its a dependent template: A<T>::template f<int>()
  • both if both: typename A<T>::template B<int>
  • typename is illegal in base-class-lists: template<class T> struct A : B<T>, C<T>::template D<int> {};
like image 138
Georg Fritzsche Avatar answered Nov 16 '22 04:11

Georg Fritzsche


This seems to work:
(EDIT: added some more lines to show the first template statement. And thanks to Samir Talwar for correcting my formatting!)

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;
};
like image 26
Beta Avatar answered Nov 16 '22 04:11

Beta