5

Visual C++ 2012. コード。コンパイルする必要があると思います。コンパイラは丁重に同意しません。再現を次のように絞り込みました。

struct  B { };

void foo(B* b, signed int si) { } // Overload 1
void foo(B const* b, unsigned int ui) { } // Overload 2

int main()
{
    B b;
    unsigned int ui;
    foo(&b, ui);
}

したがって、過負荷解決の候補が 2 つあります。最初のオーバーロードの場合、最初の引数は正確に一致し、2 番目の引数は整数変換 (符号なしから符号付き) を必要とします。2 番目のオーバーロードの場合、2 番目の引数は正確に一致し、最初の引数には cv 調整が必要です (&bは非 const へのポインターであるため)。

さて、これは完全に明白であるように思われます。オーバーロード 1 の場合、最初の引数はオーバーロードの解決に関する標準のセクションで定義されている「完全一致」ですが、2 番目の引数は「変換」です。オーバーロード 2 の場合、両方の引数が「完全一致」です (修飾変換は ID と同じランクになります)。したがって (私の明らかに不完全な推論が続く)、過負荷 2 を曖昧さなく選択する必要があります。それでも:

a.cpp(12): error C2666: 'foo' : 2 overloads have similar conversions
    a.cpp(6): could be 'void foo(const B *,unsigned int)'
    a.cpp(5): or       'void foo(B *,int)'
    while trying to match the argument list '(B *, unsigned int)'
    note: qualification adjustment (const/volatile) may be causing the ambiguity

GCC は、デフォルトの方言と C++11 (ありがとう、IDEOne!) の両方で、コードに問題ないようです。したがって、私はこれを MSVC のバグに結び付ける傾向がありますが、(a) 自分のバグをコンパイラのバグだと考えている人々について彼らが何を言っているのか知っています。(b) これはかなり明らかなバグのようです。 、適合性テスト中に危険信号を送信したであろう種類。

これは非準拠の MSVC ですか、それとも非準拠の GCC ですか? (または両方?) 過負荷の解決に関する私の推論は適切ですか?

4

1 に答える 1

7

MSVCは正しいです。

gcc 4.9.0 言います:

警告: ISO C++ は、最初の最悪の変換が 2 番目の最悪の変換よりも優れているにもかかわらず、これらはあいまいであると言います: [デフォルトで有効]

clang 3.4.1 は、2 つの関数があいまいであることに同意します。

B* => B*B* => B const*の両方にExact Matchランクがありますが、over.ics.rank/3 によると、前者は依然としてより優れた変換シーケンスです。これは(例ごとに)次のことを保証するためです。

int f(const int *);
int f(int *);
int i;
int j = f(&i); // calls f(int*)

over.ics.rank/3 から:

標準変換シーケンス S1 は、標準変換シーケンス S2 よりも優れた変換シーケンスです [...]
— S1 と S2 は修飾変換のみが異なり、それぞれ類似の型 T1 と T2 (4.4) を生成します。タイプ T1 は、タイプ T2 の cv-qualification シグネチャの適切なサブセットです。[...]

もちろん、unsigned int => unsigned intよりも優れていunsigned int => signed intます。したがって、2 つのオーバーロードのうち、1 つは最初の引数の暗黙的な変換シーケンスが優れており、もう 1 つは 2 番目の引数の暗黙的な変換シーケンスが優れています。したがって、over.match.best/1 ごとに区別することはできません。

于 2014-09-02T13:17:00.417 に答える