Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using nested class of template parameter in CRTP

Tags:

c++

Suppose I define a template T that uses a nested class of the template parameter P, as follows:

template<class P> class T
{
public:
    T(P& p) : p(p) {}
    P& p;
    typename P::Nested& get_nested()    { return p.nested; }
};

If I declare a class A that includes a nested class named Nested, I can define a variable of type T<A> with no problem:

class A
{
public:
    class Nested
    {
    public:
        int i;
    };
    Nested nested;
};

void test2a()
{
    A a;
    a.nested.i = 1;
    T<A> t_a(a);
    t_a.get_nested().i = 2;
}

Now, I want to declare a class B that, in the same way, includes a nested class named Nested and that inherits from T<B>, as follows:

class B : public T<B>
{
public:
    class Nested
    {
    public:
        int i;
    };
    Nested nested;
};

Compilation of the above code fails with error: "Nested is not a member of B"

I think I understand what's happening: at the time the template is entered, class B is incompletely defined because of inheritance.

However, I am wondering if there is any way to do such a thing...

Thanks for help.

like image 391
shrike Avatar asked Nov 20 '15 14:11

shrike


1 Answers

You need to defer the resolution of the return type of get_nested until it is called.

One way to do this is to make the return type dependent on a template parameter:

  template<typename unused = void>
    typename std::conditional<false, unused, P>::type::Nested&
    get_nested()    { return p.nested; }

Another way (since C++14) is to use return type deduction:

  auto& get_nested()    { return p.nested; }
like image 83
ecatmur Avatar answered Sep 19 '22 10:09

ecatmur