1

次のコードを参照してください。

struct X;

struct Y {
  Y() {}
  Y(X&) = delete;
};

struct X {
  X() {}
  operator Y() {
    return{};
  }
};

int main() {
  X x;
  static_cast<Y>(x);
}

ここで、Yを受け取る のコンストラクターXは明示的に削除され、 whileXには への変換演算子がありYます。これらの真っ向から対立する2つの中で、=delete常に勝つようです。GCC、Clang、および VC++ のいくつかの最近のバージョンでテストしました。

質問: それは「正しい」動作ですか? 変換コンストラクターと変換演算子の間に特に優先順位はないと思ったので、上記のコードはオーバーロード解決のあいまいさエラーを生成するはずです。しかし、そうではありません。削除された機能の使用について文句を言います。コピーの省略が保証されているためですか?

グーグルで検索して、 Conversion constructor vs. conversion operator: precedenceを見つけました。その質問ではconst、変換コンストラクターに が存在するため、より適切に一致するため、変換演算子が選択されています。ただし、私の場合、置き換えY(X&)Y(X const&)も何も変わりませんでした。


実際、私が望んでいる状況は次のとおりです。

X x;
Y y1(x);                  // Error
Y y2 = static_cast<Y>(x); // OK

X <- int&はい、これをばかげていると呼ぶかもしれませんが、実際には、そのように動作する組み込み型がありますY <- int&&。組み込みの参照型を正確に模倣するユーザー定義型を作成できないことは、現在の C++ では本当に必死に欠けている部分のようです...

4

2 に答える 2

2

スタンダードから11.6.17.6.2

初期化が直接初期化の場合、またはソース型の cv 修飾されていないバージョンが宛先のクラスと同じクラスまたは派生クラスであるコピー初期化の場合、コンストラクターが考慮されます。

次に、標準は次のことを示しています ( 11.6.16)

フォーム [...] だけでなく、new式 (8.5.2.4)、static_cast式 (8.5.1.9)、関数表記タイプの変換 (8.5.1.3)、mem-initializers (15.6.2)、および中括弧初期化リスト形式の条件は、直接初期化と呼ばれます。

あなたの例は一時的に via を初期化するstatic_castため、コンパイラは直接初期化のためにコンストラクターのみを使用できるため、エラーが発生します。

于 2018-06-29T20:46:42.157 に答える