c++ - 无复制构造函数的简单编译时间检查
问题描述
制作无副本类型的一个著名习惯用法是创建一个基类
struct NoCopy {
NoCopy(){}
NoCopy(const NoCopy&) = delete;
NoCopy& operator=(const NoCopy&) = delete;
};
并由此衍生,就像这样
struct Foo : NoCopy {
Foo(){}
};
这将使以下内容无法编译
Foo f;
Foo f2 = f;
但是我该如何执行呢?任何派生类都可以执行以下操作
struct Foo2 : NoCopy {
Foo2(){}
Foo2(const Foo2&){}
};
这是完全合法的,但没有任何意义,我现在有一个既可复制又不可复制的类型(通过它的基类)。
我该如何避免这种情况?
解决方案
这是 C++。在模板元编程的世界里,几乎一切皆有可能。如果我们创建NoCopy
一个 CRTP 基础,我们可以在其析构函数中添加静态断言。
template<class C>
struct NoCopy {
NoCopy(){}
NoCopy(const NoCopy&) = delete;
NoCopy& operator=(const NoCopy&) = delete;
~NoCopy() noexcept {
static_assert(std::is_base_of<NoCopy, C>::value, "CRTP not observed");
static_assert(!std::is_copy_constructible<C>::value, "A non-copyable copyable class? Really?");
}
};
这是您的代码,适用于现场示例。
不过,这并非没有代价,因为现在该类不是可轻易破坏的,因此也不是任何派生自它的类。能不能接受就看你自己了。
经过进一步思考,如果您只提供一种初始化类的方法,则必须引用和调用默认构造函数。所以静态断言可以移到那里,并且类型恢复到可以简单地破坏:
template<class C>
struct NoCopy {
NoCopy() noexcept {
static_assert(std::is_base_of<NoCopy, C>::value, "CRTP not observed");
static_assert(!std::is_copy_constructible<C>::value, "A non-copyable copyable class? Really?");
}
NoCopy(const NoCopy&) = delete;
NoCopy& operator=(const NoCopy&) = delete;
};
正如这个现场示例所示,静态断言的触发方式相同。
推荐阅读
- python - 从正则表达式命令中获取特定元素以进行数学表达式
- python-3.x - 创建自定义估算器
- python - Django注册表单重定向到相同的url
- c# - tablist 角色的可访问性问题
- reactjs - 使 React Query 在错误时返回以前的数据
- apache-kafka - 如何使用 avro 模式从 kafka 主题向 apache Pinot 注入数据?
- javascript - 按 1 个键对对象数组进行分组,并拆分 1 个属性
- python - 在 Python 中执行 { } while (false)
- cplex - 有没有办法在不使用 CPLEX 中的约束编程的情况下在索引范围中插入决策变量?
- rust - 无法从 Neon::types 导入 JsBox