次のコード スニペットがあります。
struct T {
T(const T&) = default;
T(const S &);
};
struct S {
operator T();
};
int main() {
S s;
T t = s; // copy-initialization of class type
return 0;
}
私の質問は、初期化があいまいであるというエラーを報告するのではなく、コンパイラが t の初期化に S::operator T() を好む理由です。私の意見では、次のことが起こります(間違っている場合は修正してください):
- t は型 S の左辺値でコピー初期化されます
- S は T ではなく、S も T のサブクラスではないため、S と T は無関係です。
- 変数 t がコピー初期化され、型 S と T が無関係であるため、コンパイラは初期化を行うためにユーザー定義の変換シーケンスを見つけようとします。
- オーバーロードの解決は、T の変換コンストラクターまたは S の変換関数のいずれかである可能性がある、最適なユーザー定義の変換を選択する責任があります。
- 引数 s からのコンストラクター T::T(const S&) の暗黙的な変換シーケンスは恒等変換です。これは、左辺値 s がこの左辺値参照に直接バインドできるためです。
- 引数 s からの変換関数 S::operator T() の暗黙的な変換シーケンスも恒等変換です。これは、暗黙的なオブジェクト パラメーターが S&
コンストラクターと変換関数の両方が、変数 t を直接初期化するために使用できる T 型の prvalue を返します。これは、両方のユーザー定義変換シーケンスの 2 番目の標準変換シーケンスが恒等変換であることを意味します。
これは、両方のユーザー定義変換シーケンスが同等に優れていることを意味します。または、変換関数を優先する特別なルールはありますか?
私はC++ 11標準で次のルールを読んでいました:
T x = a; の形式で発生する初期化。引数の受け渡し、関数の戻り、例外のスロー (15.1)、例外の処理 (15.3)、および集約メンバーの初期化 (8.5.1) と同様に、コピー初期化と呼ばれます。
初期化子のセマンティクスは次のとおりです...宛先の型が(おそらくcv修飾された)クラス型である場合: 初期化が直接初期化である場合、またはソース型のcv非修飾バージョンであるコピー初期化である場合宛先のクラスと同じクラス、またはその派生クラスである場合、コンストラクターが考慮されます....それ以外の場合 (つまり、残りのコピー初期化の場合)、ソース型から変換できるユーザー定義の変換シーケンス目的の型または (変換関数が使用されている場合) その派生クラスへの変換は、13.3.1.4 で説明されているように列挙され、オーバーロード解決 (13.3) によって最適なものが選択されます。
ユーザー定義の変換シーケンス U1 は、同じユーザー定義の変換関数またはコンストラクターを含み、U1 の 2 番目の標準変換シーケンスが U2 の 2 番目の標準変換シーケンスよりも優れている場合、別のユーザー定義の変換シーケンス U2 よりも優れた変換シーケンスです。
たぶん私は間違った仮定をしています。あなたが私を助けてくれることを願っています!