Reputation: 4839
The following will compile with GCC 5.2 but not with Visual Studio 2015.
template <typename Derived>
struct CRTP {
static constexpr int num = Derived::value + 1;
};
struct A : CRTP<A> {
static constexpr int value = 5;
};
It complains that A
does not have a member named value
.
How to fix the code so that it compiles on both compilers? Or is it illegal altogether?
Upvotes: 4
Views: 382
Reputation: 303947
The problem is here:
template <typename Derived>
struct CRTP {
static constexpr int num = Derived::value + 1;
↑↑↑↑↑↑↑↑↑
};
At the time of the instantiation of CRTP<A>
, A
isn't a complete class yet, so you can't actually access static members of it.
One workaround is to pass in num
as a separate template argument:
template <typename Derived, int N>
struct CRTP {
static constexpr int num = N;
};
struct A : CRTP<A, 5> {
};
Upvotes: 4
Reputation: 170239
Try making it a constexpr function instead. The way you have it setup now attempts to access an incomplete type.
Since a templated member function will only be initialized upon first being used, type A
will be fully defined by that point.
#include <iostream>
template <typename Derived>
struct CRTP {
static constexpr int num() { return Derived::value + 1; }
};
struct A : CRTP<A> {
static constexpr int value = 5;
};
int main()
{
std::cout << A::num();
return 0;
}
See it live here
Upvotes: 5