Is a class definition complete when passed to a base class?

I am trying to write CRTP to contain a static constexpr derived type, since this cannot be done with only one class. This code compiles in GCC, but clang complains that Derived is an incomplete type. Which one is right?

 template<class T> class Base { public: static constexpr T a = T(1), b = T(20); }; class Derived : public Base<Derived> { public: int x; constexpr Derived(int x) : x(x) {} }; 
+6
source share
1 answer

Derived is incomplete at the point at which the Base<Derived> is created ([class.mem] / 2), which happens right during the definition. You used constexpr , which requires an initializer in accordance with [class.static.data] / 3, and when creating Base<Derived> its static data members ([temp.inst] / 3), which include initializers, are also declared. However, initializers try to create an object of an incomplete type that is poorly formed.

Instead, you can declare your member as const :

 template<class T> class Base { public: static const T a; }; template <typename T> constexpr T Base<T>::a = T(1); 

since the initializer is now in the definition, an instance of this initializer can be delayed until, for example, Derived completed. Demo using Clang.

Note that Clang does not yet consider a as constexpr , because it cannot program its definition. See Bug # 24541 .

+2
source

All Articles