【发布时间】:2014-01-08 23:33:42
【问题描述】:
我有一个模板基类,期望子类将自己作为模板参数传递。
看起来有点像这样:
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 的某种技巧吗?
【问题讨论】:
-
“我有一个模板基类,期望子类将自己作为模板参数传递。”它被称为Curiously Recurring Template Pattern。
-
谢谢@dyp:我一直想要一个模式的名字。所以我认为显而易见(但丑陋)的解决方案是将常量移出其类。我怀疑在我的情况下重组事物以使类型完整是不切实际的。
-
嗯,在阅读了链接的答案和标准后,我仍然认为我的第二条(现已删除)评论是正确的:因为
Derived是Derived的“范围”内的不完整类型(名称查找推迟到类定义之后),您不能将其类型的constexpr对象创建为静态数据成员。但是,类的成员函数的定义不在其范围内。所以你应该可以使用static constexpr Derived get_LIFE() { return {42}; }
标签: c++ templates c++11 constexpr