次のように定義された Product というクラスがあるとします。
class Product
{
public:
Product(const char *name, int i);
Product(Product &&rhs);
Product(const Product &rhs);
~Product();
private:
const char *m_name;
int m_i;
};
そして、次のように変数を初期化します。
auto p = Product{"abc",123};
標準では、コンパイラが論理的に次のことを行う必要があると規定されていると思いました。
- 一時的な製品を構築する
- move-construct p (一時的な Product を使用)
しかし、p が直接構築されるように、コンパイラーがこれを最適化することが許可されていること。
私はこれを検証しました (Visual Studio 2013)。実際、独自のカスタム (既定ではない) ムーブ コンストラクターがある場合でも、コンパイラはこれを最適化します。これで問題ありません。
ただし、次のように、コピー コンストラクターとムーブ コンストラクターを明示的に削除すると、次のようになります。
class Product
{
public:
Product(const char *name, int i);
Product(Product &&rhs) = delete;
Product(const Product &rhs) = delete;
~Product();
private:
const char *m_name;
int m_i;
};
auto+brace の初期化は引き続きコンパイルされます。コピーまたは移動が許可されていないため、コンパイラはこれを防止する必要がありました。
次のように、削除されたコピー コンストラクターとムーブ コンストラクターを非公開にすると、非常に奇妙です。
class Product
{
public:
Product(const char *name, int i);
~Product();
private:
Product(Product &&rhs) = delete;
Product(const Product &rhs) = delete;
const char *m_name;
int m_i;
};
その後、auto+brace の初期化はコンパイラを実行しなくなります。
error C2248: 'Product::Product' : cannot access private member declared in class 'Product'
これは予想される動作ですか?これは Visual Studio 2013 (Update 3) のバグですか?
注: 私はideoneでこれをコンパイルしようとしましたが、コピー コンストラクターとムーブ コンストラクターが削除された (および公開された) ときに初期化をコンパイルすることを実際に拒否します。これは Visual Studio のバグだと思います。