標準化後のドラフト n3376 には、ユーザー定義型への明示的な変換関数の使用例 (12.3.2:2) があります。
class Y { };
struct Z {
explicit operator Y() const;
};
void h(Z z) {
Y y1(z); // OK: direct-initialization
}
12.3.2:2 によると、明示的な変換関数は「直接初期化のためのユーザー定義の変換としてのみ考慮されます」。ただし、次のことを許可するように見えます。
struct Y { Y(int); };
struct Z {
explicit operator int() const;
};
void h(Z z) {
Y y1(z); // direct-initialization
}
これは標準の意図と矛盾しているように見え、実際には gcc-4.7.1 によって拒否されています。
source.cpp: In function 'void h(Z)':
source.cpp:4:9: error: no matching function for call to 'Y::Y(Z&)'
source.cpp:4:9: note: candidates are:
source.cpp:1:12: note: Y::Y(int)
source.cpp:1:12: note: no known conversion for argument 1 from 'Z' to 'int'
source.cpp:1:8: note: constexpr Y::Y(const Y&)
source.cpp:1:8: note: no known conversion for argument 1 from 'Z' to 'const Y&'
source.cpp:1:8: note: constexpr Y::Y(Y&&)
source.cpp:1:8: note: no known conversion for argument 1 from 'Z' to 'Y&&'
Z
gccからY
viaへの変換を拒否するのは正しいですint
か、それとも標準で実際にこの使用法が許可されていますか?
上記の直接初期化のコンテキストを検討しました。8.5:16 のクラス型への直接初期化の定義に従って、コンストラクターは初期化式を引数として呼び出されるため、暗黙的な変換シーケンス (13.3.3.1) によってパラメーター型に変換されます。暗黙的な変換シーケンスは暗黙的な変換 (4:3) であるため、直接初期化ではなくコピー初期化 (8.5:14) をモデル化するため、12.3.2:2 の言語は式全体を参照している必要があります。
これは 12.3:4 (複数のユーザー定義の変換) の違反ではないことにも注意してください。同じコンパイラは、削除された同じコードに満足していますexplicit
(Clang と Comeau と同様):
struct Y { Y(int); };
struct Z { operator int(); };
void h(Z z) {
Y y1(z); // direct-initialization
}
operator Y
Jesse Good は 13.3.1.4:1 でとケースの違いを特定したと思いますがoperator int
、私がまだ懸念している 3 番目のケースがあります。
struct X {};
struct Y { Y(const X &); };
struct Z {
explicit operator X() const;
};
void h(Z z) {
Y y1(z); // direct-initialization via class-type X
}
X
のコンストラクターの単一const X &
パラメーターにバインドされる一時の初期化は、asおよびasY
を使用して、13.3.1.4:1 に従って直接初期化コンテキストで処理されます。この条項は正しくないと思うので、次のように読むべきです。T
X
S
Z
13.3.1.4 ユーザー定義変換によるクラスのコピー初期化 [over.match.copy]
1 - [...]オブジェクトの直接初期化のコンテキストで単一の引数で呼び出され、最初の引数としておそらくcv修飾された参照を受け取るコンストラクターの最初のパラメーターにバインドされる一時を初期化するときタイプ "cv2 "の場合、明示的な変換関数も考慮されます。[...]
T
T
混乱を避けるために、12.3.2:2 も修正する必要があると思います。
12.3.2 変換関数 [class.conv.fct]
2 - 変換関数は明示的 (7.1.2) である場合があり、その場合、特定のコンテキスト (13.3.1.4、13.3.1.5、13.3.1.6 ) での直接初期化 (8.5) のユーザー定義変換としてのみ考慮されます。 . [...]
上記について何かコメントはありますか?