異なるコンパイラによって呼び出される異なるキャスト演算子 質問する

異なるコンパイラによって呼び出される異なるキャスト演算子 質問する

次の短い C++ プログラムを考えてみましょう。

#include <iostream>

class B {
public:
    operator bool() const {
        return false;
    }
};

class B2 : public B {
public:
    operator int() {
        return 5;
    }
};

int main() {
    B2 b;
    std::cout << std::boolalpha << (bool)b << std::endl;
}

異なるコンパイラでコンパイルすると、さまざまな結果になります。Clang 3.4 および GCC 4.4.7 では が出力されますがtrue、Visual Studio 2013 では が出力されます。falseこれは、 で異なるキャスト演算子が呼び出されることを意味します(bool)b。標準に従った正しい動作はどれですか?

私の理解では、operator bool()変換は必要ありませんが、to変換がoperator int()必要になるため、コンパイラは最初のものを選択する必要があります。それに対して何かを行いますが、const 変換はコンパイラによってより「高価」であると見なされますか?intboolconst

を削除するとconst、すべてのコンパイラが同じようfalseに出力を生成します。一方、2 つのクラスを組み合わせると (両方の演算子が同じクラスになります)、3 つのコンパイラすべてがtrue出力を生成します。

ベストアンサー1

標準では次のように規定されています。

派生クラスの変換関数は、2 つの関数が同じ型に変換されない限り、基本クラスの変換関数を非表示にしません。

§12.3 [クラス.conv]

つまり、 はoperator boolによって隠されていませんoperator int

標準では次のように規定されています。

オーバーロード解決中、暗黙のオブジェクト引数は他の引数と区別できません。

§13.3.3.1 [オーバーマッチ関数]

この場合の「暗黙のオブジェクト引数」は でb、これは 型ですB2 &operator boolは を必要とするため、コンパイラは を呼び出すためconst B2 &に に const を追加する必要があります。これにより、他の条件がすべて同じであれば、より適切な一致が実現します。boperator booloperator int

標準では、次の場合にstatic_cast(このインスタンスで C スタイルのキャストが実行している) を型T(この場合はint) に変換できると規定されています。

何らかの発明された一時変数に対する宣言はT t(e);整形式ですt

§5.2.9 [式.静的.キャスト]

したがって、intは に変換できbool、 はboolに同様に変換できますbool

標準では次のように規定されています。

とその基底クラスの変換関数Sが考慮される。 と 内に隠されていない非明示的な変換関数はS、型を生成する。T Tまたは、標準の変換シーケンスを介して型に変換できる型候補関数です。

§13.3.1.5 [オーバーマッチコンバージョン]

したがって、オーバーロード セットはoperator intとで構成されますoperator bool。他の条件がすべて同じであれば、 のoperator int方が一致度が高くなります (const を追加する必要がないため)。したがってoperator intを選択する必要があります。

注意: (おそらく直感に反して) 標準では、オーバーロード セット (上記で確立) に追加された後は、一方の引数の変換シーケンスがもう一方の引数の変換シーケンスよりも優れている場合 (const のため、このインスタンスの場合はその通り)、戻り値の型 (つまり、これらの演算子が変換する型) は考慮されません。

標準では次のように規定されています。

これらの定義によれば、実行可能な関数F1は、すべての引数iに対してICSi(F1)がICSi(F2)よりも悪い変換シーケンスではない場合、他の実行可能な関数F2よりも優れた関数であると定義され、

  • ある引数jに対して、ICSj(F1)はICSj(F2)よりも優れた変換シーケンスである。そうでない場合は、
  • コンテキストはユーザー定義の変換による初期化であり、戻り値の型 F1 から宛先の型 (つまり、初期化されるエンティティの型) への標準変換シーケンスは、戻り値の型 F2 から宛先の型への標準変換シーケンスよりも優れた変換シーケンスです。

§13.3.3 [オーバーマッチベスト]

この場合、引数は 1 つだけです (暗黙のパラメータ)。 => ( を呼び出す)thisの変換シーケンスは=> ( を呼び出す)よりも優先されるため、実際には に直接変換されないという事実に関係なく、オーバーロード セットから が選択されます。B2 &B2 &operator intB2 &const B2 &operator booloperator intbool

おすすめ記事