最終更新日時(UTC):
が更新

履歴 編集

デフォルトのコピーコンストラクタと非constなコンストラクタが衝突する問題を修正(C++20)

概要

C++17までは以下のように、自身の型の非constなオブジェクトをとるコンストラクタをもつクラスを定義し、

struct MyType {
  MyType(MyType&);  // パラメータがconstではない
};

そのクラスオブジェクトをメンバ変数としてもつクラスを定義し、コピーコンストラクタをデフォルト定義すると、プログラムは不適格となってしまう。

template <typename T>
struct Wrapper {
  Wrapper(const Wrapper&) = default;
  T t;
};

Wrapper<MyType> var;  // インスタンス化に失敗する

しかし、Wrapper<MyType>をコピーしない限り、そのオブジェクトは使えるはずである。これはとくにstd::tupleの実装で問題となる。

C++20では、このコードを適格とする。

仕様

  • 明示的にデフォルト化された特殊メンバ関数のパラメータ型は、暗黙宣言された場合のパラメータ型と以下のように異なることを許可する:
    • 参照修飾が異なる
    • コピーコンストラクタとコピー代入演算子の場合、パラメータの型は「非constTへの参照」であってもかまわない
  • それ以外の方法で型が異なる場合、以下のようになる:
    • 特殊メンバ関数が代入演算子であり、戻り値の型が異なるか、パラメータの型が参照でない場合、 プログラムは不適格となる
    • そうでない場合、その特殊メンバ関数が最初の宣言で明示的にデフォルト化されていれば、その関数は削除されたものとして定義される
    • そうでない場合、プログラムは不適格となる

参照