以下肯定有效,但非常繁琐:
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&&)
,因为它可以用于两种目的。
如果没有一种明显的表达形式也是非常简洁的 - 不要寻找不要尝试语言 - 律师你的方式少写几个字。为什么?想想人们阅读你的代码:如果你需要参考标准来实现你的代码做你想做的事情那么 - 你的代码的读者也是如此。除了他们不知道你想要达到的目标;所以他们不会参考标准;所以他们只会对你的代码所做的事情感到困惑。或者 - 有些人会得到它而有些人会得到它。*
在你的情况下,如果你做了这些删除的一个子集,或使用其他一些“聪明”的技巧 - 作为一个阅读你的代码的人,我有点可能不会流行,而不是注意到你实际上是想要获得所有副本和移动语义删除。我会感到困惑,以为你正在尝试做别的事情。事实上,如果我是你,我甚至会考虑添加评论说:
/* 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 ++的杰出人物霍华德·亨南特(Howard Hinnant)就此问题发表了this to say。
* - 根据我拼写here原则的变体。
我更愿意继承boost::noncopyable,从而使意图立即明确,并将细节委托给值得信赖的图书馆。
#include <boost/core/noncopyable.hpp>
class X: private boost::noncopyable
{
};
它涉及添加一个依赖项,但是如果你对它有好处,它可以说是一种非常简洁和富有表现力的方法来实现它。
你可以写一个简单的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
}
我相信在这种情况下,宏实际上更具可读性:
#define NOT_COPYABLE( TypeName ) \
TypeName ( TypeName const& ) = delete; \
TypeName & operator = ( TypeName const& ) = delete;
#define NOT_MOVEABLE( TypeName ) \
TypeName ( TypeName && ) = delete; \
TypeName & operator = ( TypeName && ) = delete;