14

The following C++ program compiles without warnings in all compilers I have tried (gcc 4.6.3, llvm 3.0, icc 13.1.1, SolarisStudio 12.1/12.3):

struct CClass
{
  template<class T>
  operator T() const { return 1; }

  operator int() const { return 2; }
};

int main(void)
{
  CClass x;
  return static_cast<char>(x);
}

However, all but the SolarisStudio compilers return 2, SolarisStudio (either version) returns 1, which I would consider the most logical result.

Using return x.operator char(); results in all compilers returning 1.

Obviously, since figuring this out, I have been using the latter notation. However, I would like to know which of compilers is correct and why. (One would think that majority rules, but this still doesn't explain the why.)

This question seems to be related to the SO questions here, here, and here, but these "only" give solutions to problems, no explanations (that I was able to apply to my particular problem anyway).

Note that adding an additional overloaded casting operator, say operator float() const { return 3; } results in all compilers except SolarisStudio complaining about ambiguity.

4

2 に答える 2

9

最初の (テンプレート) オーバーロードを選択する必要があります

C++11 標準のパラグラフ 13.3.3/1 では、次のように指定されています。

[...] 実行可能な関数は、すべての引数に対してが よりも悪い変換シーケンスではない場合、別の実行可能な関数よりも優れF1た関数であると定義されます。 F2iICSi(F1)ICSi(F2)

— 一部の引数 に対してjICSj(F1)は よりも優れた変換シーケンスですICSj(F2)。そうでない場合は、

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

struct A {
    A();
    operator int();
    operator double();
} a;
int i = a; // a.operator int() followed by no conversion
           // is better than a.operator double() followed by
           // a conversion to int
float x = a; // ambiguous: both possibilities require conversions,
             // and neither is better than the other

—<em>例の終了] または、そうでない場合は

F1非テンプレート関数でF2あり、関数テンプレートの特殊化です。そうでない場合は、

[...]

ご覧のとおり、最初の変換演算子がテンプレートであるという事実は、その戻り値の型 (charこの場合は ) から宛先の型 (この場合は ) への標準の変換シーケンスが標準の変換よりも優れていないchar場合にのみ関連します。非テンプレート オーバーロードの戻り値の型 (この場合は ) から宛先の型 (この場合は ) へのシーケンス。intchar

ただし、 からcharへの標準的な変換charExact Matchintですが、 からへの標準的な変換はそうでcharはありません。したがって、§ 13.3.3/1 の 3 番目の項目は適用されず、2 番目の項目は適用されます。

これは、最初の (テンプレート) オーバーロードを選択する必要があることを意味します。

于 2013-05-19T14:59:18.853 に答える