CRTP 单一实例不完整类型或非文本类型
CRTP Singleton Incomplete type or Non-literal type
我正在尝试制作一个CRTP单例。这里已经有几个例子了。我不确定我的有什么不同,或者为什么它无法编译。第一次尝试:
template<class Impl>
class Base
{
public:
static const Impl& getInstance();
static int foo(int x);
private:
static const Impl impl{};
};
template<class Impl> inline
const Impl& Base<Impl>::getInstance()
{
return impl;
}
template<class Impl> inline
int Base<Impl>::foo(int x)
{
return impl.foo_impl(x);
}
class Derived1 : public Base<Derived1>
{
public:
int foo_impl(int x) const;
};
int Derived1::foo_impl(int x) const
{
return x + 3;
}
int main(int argc, char** argv)
{
const Derived1& d = Derived1::getInstance();
std::cout << Derived1::foo(3) << std::endl;
return 0;
}
G++ 7.4.0 告诉我:error: in-class initialization of static data member ‘const Derived1 Base<Derived1>::impl’ of incomplete type
.
井。那好吧。不知道为什么该类型不完整。尝试:
. . .
private:
static constexpr Impl impl{};
};
现在我们在链接时失败:undefined reference to 'Base<Derived1>::impl'
真?!看起来对我来说是定义和初始化的...但即使它确实链接了我有一个带有非平凡析构函数的派生,所以编译器将在编译时轰炸抱怨 constexpr 中使用的非文字类型。
为什么派生 1 不完整?我该如何构建它?
不完整的类型错误来自您在getInstance
存在之前在中使用impl
的事实。
解决此问题的一种方法是在类定义之外初始化impl
并确保在使用之前对其进行初始化:
template <class Impl>
const Impl Base<Impl>::impl {};
尝试以这种方式实现getInstance
函数:
template <class Impl>
inline const Impl& Base<Impl>::getInstance() {
static const Impl impl{};
return impl;
}
然后在foo
函数中
template <class Impl>
inline int Base<Impl>::foo(int x) {
return getInstance().foo_impl(x);
}
演示
在Base<Derived1>
被实例化的时间点(就在Derived1
定义的开头(,类Derived1
是不完整的,因为它直到它的声明结束。CRTP 中确实不可能有一个完整的类型,因为在声明其继承之前,派生类型永远不会完整。
对于非静态数据成员,唯一的解决方法是使用某种指向不完整类型的指针(很可能是std::unique_ptr
(。对于静态成员,这也有效,但也可以拆分静态成员的声明和定义。所以而不是
template<Impl>
struct Base {
static Impl impl{};
};
写
template<Impl>
struct Base {
static Impl impl;
};
并像这样定义它
template<Impl>
static Base<Impl>::impl ={};
Derived1
完成后。(请注意,我不确定这对私有静态成员是如何工作的(。在我看来,如果每个实现都为自己执行此操作,即在Derived1
完成后添加
template<>
static Base<Derived1>::impl = {};
否则,我认为为多个实现获得正确的顺序将很棘手。
- CRTP 单一实例不完整类型或非文本类型
- 如何从文本文件中读取数值,直到遇到字符类型?
- 如何将文本文件的特定行读取到 int 类型的数组中C++?
- 文本冒险游戏 - 如何区分一种项目类型与另一种项目类型以及如何构建项目类/子类
- 是否可以创建一个用户定义的文本,将字符串文本转换为 own 类型的数组?
- 如何使用C++将.trc文件类型转换为文本文件?
- 整数文本太大,无法用任何整数类型表示--C++
- 具有引用数据成员的结构不是文本类型吗?
- 指针类型是文本类型吗?
- FindResource 调用返回 RCDATA 类型的文本文件的 NULL
- 文本类类型成员函数约束
- 当浮点数文本直接分配给不同的类型时,编译器如何处理浮点文字?
- 如何在自由类型中获取文本宽度
- 常量表达式中的非文本类型'compare'
- C++文本整数类型
- 运行时文本类型的惊人行为
- 在C 中按行读取文本文件,每行都是不同的数据类型
- 设计具有变体字段的文本类型类,其中可以存储一个或三个对象
- (视觉-)C++ 字符串文本的模板类型推断 - VS 2010 与 VS 2017
- QString:包括非文本类型的静态数据成员的初始化