5

Visual C++ 2012. Код. Я думаю, он должен скомпилировать; компилятор с уважением не согласен. Я сузил репродукцию до:Неожиданно неоднозначное разрешение перегрузки в VC++ 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); 
} 

Итак, у нас есть два кандидата для разрешения перегрузки. Для первой перегрузки первый аргумент точно соответствует, а для второго аргумента требуется интегральное преобразование (без знака для подписания). Для второй перегрузки второй аргумент точно соответствует, и для первого аргумента требуется cv-настройка (потому что &b является указателем на неконстантный).

Теперь, кажется, это должно быть абсолютно однозначным. Для Overload 1 первым аргументом является «Точное соответствие», как определено разделом стандарта о разрешении перегрузки, а второе - «Конверсия». Для Overload 2 оба аргумента - «Точные совпадения» (преобразование квалификации имеет тот же ранг, что и личность). Поэтому (мои, по-видимому, несовершенные рассуждения), следует выбрать Overload 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, но (а) вы знаете, что они говорят о людях, которые думают, что их ошибки являются ошибками компилятора, и (б) похоже, что это будет довольно очевидная ошибка , сортировка, которая отправила бы красные флаги во время их тестирования соответствия.

Является ли это несоответствующим MSVC или несоответствующим GCC? (Или и то, и другое?) Является ли мое рассуждение относительно звука с перегрузкой?

+1

Я не знаю, какой компилятор прав, но, как человек, я предпочитаю знать, какая перегрузка будет использоваться без необходимости двусмысленности на основе «приоритета» двух типов преобразований :-) – Cameron

+0

@Cameron О, я дать согласие. Фактический прецедент делает намного больше смысла, и действительно * выглядит * однозначным. – Sneftel

ответ

7

MSVC правильный.

GCC 4.9.0 говорит:

предупреждение: ISO C++ говорит, что эти неоднозначны, хотя худшее преобразование для первого лучше, чем наихудших преобразований для второго: [по умолчанию включено]

clang 3.4.1 соглашается, что две функции неоднозначны.

Хотя B* => B* и B* => B const*оба имеют точное совпадение ранга, бывший еще лучше последовательность преобразования в 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) соответственно, а cv-квалификационная сигнатура типа T1 является собственным подмножеством cv-квалификационной сигнатуры типа T2. [...]

И, конечно, unsigned int => unsigned int лучше, чем unsigned int => signed int. Итак, из двух перегрузок, у одного есть более эффективная неявная последовательность преобразований по первому аргументу, а вторая имеет более лучшую неявную последовательность преобразования во втором аргументе. Таким образом, их нельзя отличить за over.match.best/1.

+0

Спасибо. Так в чем же причина в моих рассуждениях? Кажется, из моего чтения Стандарта нет преобразования для перегрузки 2, которое хуже, чем соответствующее преобразование для перегрузки 1, - что компилятор не должен предпочитать 'B *' 'B const *' при сравнении перегрузок. – Sneftel

+0

@Sneftel ах, но он делает - я добавлю точные формулировки. – ecatmur

+0

Да, только что нашел. Похоже, я перестал читать слишком рано. Спасибо, что копали. – Sneftel

 Смежные вопросы

  • Нет связанных вопросов^_^