3

この標準は、ユーザー定義の変換演算子を含む暗黙の変換シーケンスを区別するための2つのルールを提供しているようです。

13.3.3最高の実行可能な関数[over.match.best]

[...]実行可能な関数F1は、[...]の場合、別の実行可能な関数F2よりも優れた関数であると定義されます。

  • コンテキストはユーザー定義の変換による初期化であり(8.5、13.3.1.5、および13.3.1.6を参照)、F1の戻りタイプから宛先タイプ(つまり、初期化されるエンティティのタイプ)への標準変換シーケンスは次のとおりです。 F2の戻りタイプから宛先タイプへの標準変換シーケンスよりも優れた変換シーケンス。

13.3.3.2暗黙の変換シーケンスのランク付け[over.ics.rank]

3-次の規則のいずれかが適用されない限り、同じ形式の2つの暗黙的な変換シーケンスは区別できない変換シーケンスです。[...]

  • ユーザー定義の変換シーケンスU1は、同じユーザー定義の変換関数またはコンストラクターまたは集約初期化を含み、U1の2番目の標準変換シーケンスが2番目の標準変換シーケンスよりも優れている場合、別のユーザー定義の変換シーケンスU2よりも優れた変換シーケンスです。 U2の。

私が理解しているように、13.3.3を使用すると、コンパイラはさまざまなユーザー定義の変換演算子を区別できますが、13.3.3.2を使用すると、コンパイラは、引数にユーザー定義の変換が必要なさまざまな関数(一部の関数のオーバーロード)を区別できます。 f((GCC 4.3の)次のコードが与えられた場合のサイドバーを参照してください。参照への変換が2回呼び出されるのはなぜですか?

ユーザー定義の変換シーケンスを区別できる他のルールはありますか?https://stackoverflow.com/a/1384044/567292での回答は、13.3.3.2:3が、(変換演算子に対する)暗黙のオブジェクトパラメーターのcv-qualificationに基づいて、ユーザー定義の変換シーケンスを区別できることを示しています。コンストラクターまたは集計の初期化に対する単一のデフォルト以外のパラメーターですが、それぞれのユーザー定義の変換シーケンスの最初の標準変換シーケンス間の比較が必要になることを考えると、それがどのように関連するかわかりません。言及しているようです。

S1がS2よりも優れていると仮定すると(S1はU1の最初の標準変換シーケンスであり、S2はU2の最初の標準変換シーケンスです)、U1はU2よりも優れているということになりますか?言い換えれば、このコードは整形式ですか?

struct A {
    operator int();
    operator char() const;
} a;
void foo(double);
int main() {
    foo(a);
}

g ++(4.5.1)、Clang(3.0)、Comeau(4.3.10.1)はそれを受け入れ、非const-qualifiedを優先A::operator int()しますが、あいまいで形式が正しくないために拒否されると思います。これは標準の欠陥ですか、それとも私の理解の欠陥ですか?

4

1 に答える 1

6

ここでの秘訣は、クラス型から非クラス型への変換では、実際にはユーザー定義の変換が暗黙的な変換シーケンスとしてランク付けされないことです。

struct A {
    operator int();
    operator char() const;
} a;
void foo(double);
int main() {
    foo(a);
}

foo(a)では、foo明らかにオーバーロードされていない非メンバー関数の名前です。この呼び出しでは、クラス type の左辺値であるdouble単一の式 を使用して、 type の関数パラメーターをコピー初期化 (8.5p14) する必要があります。aA

宛先の型doubleは cv 修飾されたクラス型ではなく、ソースの型A であるため、候補関数はセクション 13.3.1.5 でS=Aおよびで定義されT=doubleます。Aclassおよび の基本クラスの変換関数のみAが考慮されます。次の場合、変換関数は候補のセットに含まれます。

  • クラスに隠されておらずA
  • そうではなくexplicit(コンテキストがコピー初期化であるため)、かつ
  • 標準の変換シーケンスでは、関数の戻り値の型 (参照修飾子を含まない) を変換先の型に変換できますdouble

さて、両方の変換関数が適格であるため、候補関数は次のとおりです。

A::operator int();        // F1
A::operator char() const; // F2

13.3.1p4 の規則を使用すると、各関数は、そのパラメーター リスト内の唯一のものとして、暗黙的なオブジェクト パラメーターを持ちます。 F1のパラメータ リストは「(への左辺値参照A)」であり、F2のパラメータ リストは「(への左辺値参照const A)」です。

次に、関数が実行可能であることを確認します (13.3.2)。各関数のパラメーター リストには 1 つの型があり、1 つの引数があります。各引数/パラメーターのペアに暗黙的な変換シーケンスはありますか? もちろん:

  • ICS1(F1): 暗黙のオブジェクト パラメーター ( への型左辺値参照A) を式a(型 の左辺値) にバインドしますA
  • ICS1(F2): 暗黙のオブジェクト パラメーター ( への型左辺値参照const A) を式a(型 の左辺値) にバインドしますA

派生からベースへの変換は行われないため、これらの参照バインディングは ID 変換 (13.3.3.1.4p1) の特殊なケースと見なされます。うん、両方の機能が実行可能です。

ここで、1 つの暗黙的な変換シーケンスが他のものよりも優れているかどうかを判断する必要があります。これは、13.3.3.2p3 の大きなリストの 5 番目のサブ項目に該当します。どちらも、トップレベルの cv 修飾子を除いて、同じ型への参照バインディングです。の参照される型は、ICS1(F2)の参照される型よりも cv 修飾されているためICS1(F1)ICS1(F1)は よりも優れていICS1(F2)ます。

したがってF1、 、またはA::operator int()が最も実行可能な機能です。また、ユーザー定義の変換 (SCS + (変換コンストラクターまたは変換関数) + SCS で構成される ICS の型の厳密な定義による) も比較対象ではありませんでした。

オーバーロードされた場合foo、引数のユーザー定義の変換をa比較する必要があります。したがって、ユーザー定義の変換 (identity + A::operator int()+ intto double) は、他の暗黙的な変換シーケンスと比較されます。

于 2012-07-25T02:21:46.077 に答える