web-dev-qa-db-ja.com

ムーブコンストラクタとムーブ代入演算子をシングルトンで削除する必要があるのはなぜですか?

次のシングルトンポリシークラスの実装があります。

template <typename T>
class Singleton
{
    Singleton(){}; // so we cannot accidentally delete it via pointers
    Singleton(const Singleton&) = delete; // no copies
    Singleton& operator=(const Singleton&) = delete; // no self-assignments
    Singleton(Singleton&&) = delete; // WHY?
    Singleton& operator=(Singleton&&) = delete; // WHY?
public:
    static T& getInstance() // singleton
    {
        static T instance; // Guaranteed to be destroyed.
                       // Instantiated on first use.
                       // Thread safe in C++11
        return instance;
    }
};

次に、不思議なことに繰り返されるテンプレートパターン(CRTP)を介して使用します

class Foo: public Singleton<Foo> // now Foo is a Singleton
{
    friend class Singleton<Foo>;
    ~Foo(){}
    Foo(){};
public:
// rest of the code
};

移動コンストラクターと代入演算子を削除する必要がある理由がわかりません。移動ctorと代入演算子を削除しない(まったく定義しない)と、シングルトンを壊してしまう例を1つ挙げてください。

17
vsoftco

コピーコンストラクターを宣言する場合(宣言でdeletedとして定義した場合でも)、移動コンストラクターは暗黙的に宣言されません。 Cf. C++ 11 12.8/9:

クラスXの定義で移動コンストラクターが明示的に宣言されていない場合、次の場合に限り、デフォルトとして暗黙的に宣言されます。

— xには、ユーザーが宣言したコピーコンストラクターがありません。

—.。

ユーザーが宣言したコピーコンストラクターがあるので、宣言しないと移動コンストラクターはまったくありません。したがって、moveコンストラクターの宣言定義を完全に取り除くことができます。ムーブ代入演算子についても同じです。

34
Kerrek SB