The base class in the CRTP pattern can access the member functions of the derived class, but it can't access a nested type in the derived class.
Why this difference?
To illustrate, consider the following piece of code:
template<typename Derived>
struct crtp_base
{
void crtp_method() { return static_cast<Derived&>(*this).method(); } // compiles
using crtp_type = typename Derived::type; // doesn't compile
};
struct X : public crtp_base<X>
{
void method() {}
using type = int;
};
int main()
{
}
crtp_type
causes a compilation error, while crtp_method
compiles fine, although both attempt to access something defined in the Derived
class. What is the C++ specification that explains that difference?
The difference here is that instantiation of method happens only when you actually use it while instantiation of crtp_base
happens at public crtp_base<X>
where type X
is still incomplete. The workaround would be to use type traits:
template<typename x_Target>
struct Trait;
template<typename Derived>
struct crtp_base
{
void crtp_method() { return static_cast<Derived&>(*this).method(); }
using crtp_type = typename Trait<Derived>::type;
};
struct X;
template<>
struct Trait<X>
{
using type = int;
};
struct X : public crtp_base<X>
{
void method() {}
using type = Trait<X>::type;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With