1
struct X {
      X() {}
      X(X&&) { }
};
X global_m;

struct Converts {
        operator X&& () const { return std::move(global_m); }
};

私は以下がうまくいくはずだと信じています:

X x { Converts{} };

X の引数が 1 つのコンストラクターは 1 つだけX&&です。Converts オブジェクトは一時的なもので、 に変換されX&&ます。では、clang-3.3 から次のエラー メッセージが表示されるのはなぜですか。

 // error: "candidate constructor not viable: no known conversion from 'Converts' to 'X &&' for 1st argument"

次のように明示的に演算子を呼び出すことができます。

X x { Converts{}.operator struct X&& () }; // this works.

残念ながら、私が知る限り g++ に基づくideoneで動作します。現在稼働中のオンラインのclangコンパイラはありますか?

4

1 に答える 1

1

この回答によると、それは標準の欠陥でした。これは、@ecatmur が提案した標準に対する修正です。

4 - ただし、候補であるコンストラクターまたはユーザー定義の変換関数の引数を考慮する場合:

  • 13.3.1.3 [over.match.ctor] により、クラスのコピー初期化の 2 番目のステップで一時的なコピーのために呼び出された場合、または
  • すべての場合において、13.3.1.4 [over.match.copy]、13.3.1.5 [over.match.conv]、または 13.3.1.6 [over.match.ref] によって、

標準の変換シーケンスと省略記号の変換シーケンスのみが考慮されます。13.3.1.7 [over.match.list] で候補となるクラスのコンストラクターの最初の引数を考慮するX場合 イニシャライザー リストを単一の引数として渡す場合、またはイニシャライザー リストに要素が 1 つだけある場合、ユーザー定義の変換toXまたは reference to (おそらくcv修飾)Xは、そのユーザー定義の変換が変換関数によって指定されている場合にのみ考慮されます。[注:リスト初期化のコンテキストでは、暗黙的な変換シーケンスで複数のユーザー定義の変換が許可されるため、この制限は、 の変換コンストラクターがX単一の引数で呼び出されることを保証するために必要です。aXまたは から派生した型ではない は、 から構築された一時オブジェクト自体Xで呼び出された のコンストラクターに対してあいまいではありません。-- 巻末注記XXa

これが正確に標準が変更された方法であるかどうかはわかりませんが(ドラフトしかないため)、コンパイラのバージョンに応じて結果が変更されたため、何かが行われたと思います

于 2013-11-03T22:48:14.407 に答える