以下肯定有效,但非常繁琐:
T(const T&) = delete;
T(T&&) = delete;
T& operator=(const T&) = delete;
T& operator=(T&&) = delete;
我正在尝试发现最简洁的方法。以下是否有效?
T& operator=(T) = delete;
更新
请注意,我选择的是T& operator=(T)
而不是T& operator=(const T&)
或T& operator=(T&&)
,因为它可以同时满足这两个目的。
答案 0 :(得分:22)
根据此图表(Howard Hinnant):
最简单的简洁方式是=delete
移动赋值运算符(或移动构造函数,但它可能会导致注释中提到的问题)。
尽管如此,在我看来,可读方式是=delete
两种复制构造函数和复制赋值运算符。
答案 1 :(得分:4)
如果没有一种明显的表达形式也是非常简洁的 - 不要寻求不要以语言 - 律师的方式去写少数几个字。为什么?想想阅读代码的人:如果你需要查阅标准来实现你的代码做你想做的事情那么 - 那么代码的读者也是如此。除了他们不知道你想要实现什么;所以他们不会参考标准;所以他们只会对你的代码所做的事情感到困惑。或者 - 有些人会得到它而有些人不会。 *
在你的情况下,如果你做了这些删除的一个子集,或者使用其他一些"聪明的"诀窍 - 作为一个阅读你的代码的人,它有点可能我不会流行,而不是注意到你实际上试图让所有的复制和移动语义被删除。而且我会感到困惑,以为你正在尝试做别的事情。事实上,如果我是你,我甚至会考虑添加评论说:
/* Disabling copy and move semantics because XYZ */
T(const T&) = delete;
T(T&&) = delete;
T& operator=(const T&) = delete;
T& operator=(T&&) = delete;
这更加繁琐",但会使你的意图/动机对你未来的读者绝对清楚。
还有一个问题是" XYZ"原因是。有些人认为删除移动成员没有充分的理由,这样做通常是个坏主意。 C ++的杰出人物霍华德·亨南特就此问题this to say。
* - 根据我拼写here原则的变体。
答案 2 :(得分:3)
我更愿意继承boost::noncopyable,从而立即明确意图,并将细节委托给值得信赖的图书馆。
#include <boost/core/noncopyable.hpp>
class X: private boost::noncopyable
{
};
它涉及添加一个依赖项,但是如果你对此感到满意,它可以说是一种非常简洁和富有表现力的方法来实现它。
答案 3 :(得分:2)
你可以写一个简单的struct
并从中继承:
struct crippled
{
crippled() = default;
crippled(const crippled&) = delete;
crippled(crippled&&) = delete;
crippled& operator=(const crippled&) = delete;
crippled& operator=(crippled&&) = delete;
};
用法:
struct my_class : crippled
{
};
int main()
{
my_class a;
auto b = a; // fails to compile
}
答案 4 :(得分:-1)
我相信在这种情况下,宏实际上更具可读性:
#define NOT_COPYABLE( TypeName ) \
TypeName ( TypeName const& ) = delete; \
TypeName & operator = ( TypeName const& ) = delete;
#define NOT_MOVEABLE( TypeName ) \
TypeName ( TypeName && ) = delete; \
TypeName & operator = ( TypeName && ) = delete;