我有一个模板基类,期望子类将自己作为模板参数传递。
看起来有点像这样:
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);
编译并按预期工作。但现在我想让Derived :: LIFE成为一个constexpr。这甚至可能吗?
我不能将它的const限定符更改为constexpr,因为constexpr需要在其声明中初始化:
test.cpp:10:28: error: constexpr static data member ‘LIFE’ must have an initializer
static constexpr Derived LIFE;
我无法在那里初始化它,因为Derived是一个不完整的类型:
test.cpp:10:45: error: invalid use of incomplete type ‘struct Derived’
static constexpr Derived LIFE = Derived(42);
如果Derived是一个完整的类型,我意识到这个问题会消失,但在这个特殊情况下,我非常依赖于自引用的模板化基类,原因与此问题无关。
如果我正确地理解this answer中的最后一段,听起来至少有一些关于改变未来某个时候处理不完整类型的方式的讨论,但这对我现在没有帮助。
是否有人知道在我的上述代码中推迟LIFE初始化的某种技巧?
答案 0 :(得分:5)
您只需将constexpr
添加到LIFE
:
constexpr Derived Derived::LIFE = Derived(42);
直到最近GCC还有一个错误,它拒绝了这个;你需要使用Clang或GCC 4.9。
答案 1 :(得分:4)
我认为你应该使用lazy initialization。实际上Derived
仍然是不完整的类型;因为编译器还不知道它的大小。
所以代码应该是:
struct Derived : public Base<Derived>
{
constexpr Derived(int x) : Base(x) {}
static constexpr Derived getLIFE()
{
return Derived(34);
}
};
修改强>
使用此代码段可以重现相同的incomplete type
行为:
struct MyStruct
{
static constexpr int x = sizeof(MyStruct);
};