Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use nested class of templated class as template template parameter in C++

In C++, I'd like to use a nested class inside a templated class as template template parameter. For non-nested classes the pattern is:

template<class T>
class A {
public:
    T a;
    // ...
};

template<class T, template<class ST> class S>
class B {
public:
    S<T> b;
    // ...
};

B<int, A> b;

Now I'd like to add a nested class to A and use this nested class as template template parameter S of class B, like this:

template<class T>
class A {
public:
    class AA {
    public:
        T aa;
        // ...
    };
    // ...
};

template<class T, template<class ST> class S>
class B {
public:
    S<T> b;
    // ...
};

B<int, A> b1;          // ok
B<int, A::AA> b2;      // error
B<int, A<int>::AA> b3; // error

I understand that the declarations of b2 and b3 are errors because A::AA is incomplete and A<int>::AA is not a template.

I would like to be able to declare something similar to b2. The idea is that A and B should both use the same class T.

I would like to be able to declare a number of classes similar to A with individually named sub-classes. Another use of this I can think of are multiple sub-classes of A that can be used as template template parameter to B.

One workaround I see is to refrain from using individual names on the sub-classes of A, use the b1 declaration (use A as template template parameter S for B) and change the implementation of B accordingly (i.e. use S::AA<T> instead of S<T>):

template<class T, template<class ST> class S>
class B {
public:
    S::AA<T> b;
    // ...
};

B<int, A> b;

The other workaround I see is to reduce the template template parameter of class B to a simple template parameter, and ensure the same T by other means.

Is there some other possibility? If yes, how?

Edit: Added forgotten class in template for B and changed template template parameter name to ST.

like image 937
Robin Avatar asked Mar 17 '17 11:03

Robin


2 Answers

This works for me:

template<class T>
class A {
public:
    class AA {
    public:
        T aa;
        // ...
    };
    // ...
};

template<class T, template<class ST> class S >
class B {
public:
    S<T> b;
    // ...
};

template<class T> using NestedAA = typename A<T>::AA;

int main()
{
  B<int, NestedAA> b; // ok

  return 0;
}

If for any reason you are constrained to C++03, type aliases won't be available to you. You can then replace the "using" statement with the following definition for NestedAA:

template<class T>
class NestedAA : public A<T>::AA
{
};
like image 138
Matteo Mecucci Avatar answered Nov 15 '22 12:11

Matteo Mecucci


You may create an template alias:

template <typename T>
using innerAA = typename A<T>::AA;

and then

B<int, innerAA> b42;

Demo

like image 25
Jarod42 Avatar answered Nov 15 '22 12:11

Jarod42