Using a nested template parameter class in CRTP

Suppose I define a pattern T that uses the nested class of the pattern 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 called Nested , I can define a variable of type T<A> without any problems:

 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 called Nested and which inherits from T<B> as follows:

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

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

I think I understand what is going on: when entering the template, class B is not fully defined due to inheritance.

However, I wonder if there is a way to do this ...

Thanks for the help.

+5
source share
2 answers

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

One way to do this is to make the return type dependent on the 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 inference:

  auto& get_nested() { return p.nested; } 
+6
source

I was able to compile your example simply

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

Another approach using the same trick as @ecatmur, but a bit simpler:

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

Similarly, here the compiler should defer the evaluation of P::Nested until you call get_nested() .

+3
source

Source: https://habr.com/ru/post/1236434/


All Articles