Access to nested names requires the class to be complete, but Derived is not yet complete:
template<typename Derived> struct Base { static constexpr int x_base = Derived::x_derived; ^^^^^^^^^ };
therefore, the code is poorly formed.
There are several workarounds. First, you can separately pass the value as an argument to the template:
template <typename Derived, int x_derived> struct Base { static constexpr int x_base = x_derived; }; struct Derived : public Base<Derived, 5> { };
Secondly, if possible (for example, you do not need x_derived declare any elements), you can move the value to a function to delay its creation:
template<typename Derived> struct Base { static constexpr int x_base() { static_assert(Derived::x_derived > 1, "Oops"); return Derived::x_derived; } }; struct Derived : public Base<Derived> { static constexpr int x_derived = 5; };
Barry source share