传递给基类时,类定义是否完整?

use*_*989 6 c++ language-lawyer c++11

我正在尝试编写一个包含static constexpr派生类型的CRTP ,因为这对于一个类是不可能的.这段代码在GCC中编译得很好,但是clang抱怨这Derived是一个不完整的类型.哪一个是对的?

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) {}
};
Run Code Online (Sandbox Code Playgroud)

Col*_*mbo 2

Derived在实例化点Base<Derived>([class.mem]/2) 不完整,这发生在定义时。您使用了constexpr,它需要一个根据 [class.static.data]/3 的初始化程序,并且在Base<Derived>实例化时,其静态数据成员 ([temp.inst]/3) 的声明也是如此,其中包括初始化程序。但是,初始化程序尝试创建不完整类型的对象,该对象的格式不正确。

您可以将您的成员声明为const

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

由于初始化器现在位于定义处,因此可以推迟该初始化器的实例化,直到egDerived完成。使用 Clang 进行演示。

请注意,Clang 尚未将aas视为constexpr因为它无法急切地实例化其定义。请参阅错误#24541