由于模板基类而从不完整的类型初始化静态constexpr

Mar*_*tin 3 c++ templates constexpr c++11

我有一个模板基类,期望子类将自身作为模板参数传递。

看起来有点像这样:

template<typename T>
struct Base {
    constexpr Base(int x) : m_x(x) {}
private:
    int m_x;
};

struct Derived : public Base<Derived>
{
    static const Derived LIFE;
    constexpr Derived(int x) : Base(x) {}
};

const Derived Derived::LIFE = Derived(42);
Run Code Online (Sandbox Code Playgroud)

编译并按预期工作。但是现在我想将Derived :: LIFE设为constexpr。这有可能吗?

我不能只将它的const限定符更改为constexpr,因为constexpr需要在其声明中进行初始化:

test.cpp:10:28: error: constexpr static data member ‘LIFE’ must have an initializer
   static constexpr Derived LIFE;
Run Code Online (Sandbox Code Playgroud)

由于Derived是不完整的类型,因此无法在其中初始化:

test.cpp:10:45: error: invalid use of incomplete type ‘struct Derived’
   static constexpr Derived LIFE = Derived(42);
Run Code Online (Sandbox Code Playgroud)

我知道,如果Derived是完整类型,则此问题将消失,但是由于与该问题无关的原因,在这种特殊情况下,我非常喜欢使用自引用模板化基类。

如果我正确地理解了此答案的最后一段,听起来似乎至少有一些讨论会在将来的某个时候更改不完整类型的处理方式,但是现在对我无济于事。

有人知道我上面的代码中有一些技巧可以推迟LIFE的初始化吗?

Ric*_*ith 5

您可以简单地添加constexpr到的定义LIFE

constexpr Derived Derived::LIFE = Derived(42);
Run Code Online (Sandbox Code Playgroud)

直到最近,GCC还是有一个bug拒绝了它。您需要使用Clang或GCC 4.9。


You*_*usf 4

我认为你应该使用延迟初始化。其实Derived还是不完整类型;因为编译器还不知道它的大小。

所以代码应该是:

struct Derived : public Base<Derived>
{
    constexpr Derived(int x) : Base(x) {}

    static constexpr Derived getLIFE()
    {
        return Derived(34);
    }
};
Run Code Online (Sandbox Code Playgroud)

编辑:incomplete type可以使用以下代码片段重现 相同的行为:

struct MyStruct
{
    static constexpr int x = sizeof(MyStruct);
};
Run Code Online (Sandbox Code Playgroud)