以下は確かに機能しますが、非常に退屈です。
_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&&)
を選択していることに注意してください。
あなたは単純な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
}
私は boost :: noncopyable から継承することを好むので、意図がすぐに明確になり、詳細が信頼できるライブラリに委任されます。
#include <boost/core/noncopyable.hpp>
class X: private boost::noncopyable
{
};
依存関係を追加する必要がありますが、それに問題がなければ、間違いなくそれを実現するための非常に簡潔で表現力のある方法です。
非常に簡潔な何かを表現する明白な形式がない場合は、数文字を減らすために言語弁護士に頼らないでください。どうして?あなたのコードを読んでいる人のことを考えてください。もしあなたのコードがあなたがしたいことをすることを実現するために標準を調べる必要があるなら-そしてあなたのコードの読者もそうするでしょう。彼らがあなたが達成しようとしていることを知らないことを除いて。そのため、彼らは標準を参照しません。ですから、彼らはあなたのコードが何をするかについて混乱するだけです。または-一部はそれを取得し、一部はしません。*
あなたの場合、これらの削除のサブセットを作成するか、他の「巧妙な」トリックを使用すると、コードを読む人として、私が追いつかない可能性が高く、実際にすべてのコピーを取得しようとしていることに気付かない移動セマンティクスが削除されました。そして、私はあなたが何か他のことをしようとしていると思って混乱します。実際、もし私があなただったら、次のようなコメントを追加することも検討します。
/* 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++の著名なハワードヒナントは、この問題について これは言う を持っています。
*-私が綴った原則の変形 here 。
この場合、マクロは実際にはもっと読みやすいと思います:
#define NOT_COPYABLE( TypeName ) \
TypeName ( TypeName const& ) = delete; \
TypeName & operator = ( TypeName const& ) = delete;
#define NOT_MOVEABLE( TypeName ) \
TypeName ( TypeName && ) = delete; \
TypeName & operator = ( TypeName && ) = delete;