Разрешение перегрузки С++ - неоднозначное совпадение

Я пытался поэкспериментировать с некоторыми базовыми концепциями разрешения перегрузок, используя следующий тестовый код:

void foo()
{
   void F(int x, int y);        // F1
   void F(char x, double y);    // F2
   F('A', 5);
}

Я «пытался» понять применимые части стандарта С++ 17, а также просмотрел сайт cppreference.com. Насколько я понимаю, последовательность преобразования для F1 состоит из повышения и точного совпадения, тогда как последовательность преобразования для F2 состоит из точного совпадения и преобразования. cppreference.com частично заявляет, что

...
F1 is determined to be a better function than F2 if implicit conversions for all 
arguments of F1 are not worse than the implicit conversions for all arguments of 
F2, and
1) there is at least one argument of F1 whose implicit conversion is better than 
the corresponding implicit conversion for that argument of F2
...

Основываясь на всем вышесказанном, я подумал, что F1 должен быть принят как лучший кандидат, потому что худшая конверсия для F1 лучше, чем худшая конверсия для F2. Однако компиляторы Microsoft и minGW генерируют «неоднозначную» ошибку совпадения. Так что, очевидно, я что-то упускаю. Я был бы признателен за объяснение того, что мне не хватает, и ссылку на эту информацию в С++ 17. Спасибо!


person BenevolentDeity    schedule 29.04.2020    source источник


Ответы (1)


При выяснении того, какую функцию вызывать, сначала вычисляются все жизнеспособные кандидаты. Затем каждая из этих функций упорядочивается в соответствии с количеством необходимых неявных преобразований. Итак, учитывая вызов:

F('a', 5);

какие неявные преобразования необходимо выполнить?

F1 // 1st argument: char -> int
   // 2nd argument: int -> int (none)

F2 // 1st argument: int -> int (none)
   // 2nd argument: int -> double 

поскольку и F1, и F2 должны выполнять ровно одно неявное преобразование каждый, они оба считаются одинаково хорошими, и вызов неоднозначен. В частности, оба этих преобразования имеют одинаковый ранг, т. е. выполняют интегральное продвижение и продвижение с плавающей запятой соответственно.

Очевидно, что существует больше правил, которые охватывают большее количество случаев, но в этом случае между двумя функциями нет разграничителя.

person cigien    schedule 29.04.2020
comment
Спасибо за ваш быстрый ответ. Для F2 преобразование второго аргумента — int->double. Кроме того, вы говорите, что для функций с одинаковым количеством параметров, где все параметры имеют различные арифметические типы, наиболее жизнеспособный кандидат полностью основан на том, что имеет меньше неявных преобразований, чем любой из других, независимо от рангов последовательности преобразования? - person BenevolentDeity; 29.04.2020
comment
Правильно, отредактировал ответ. Я считаю, что ранг имеет значение, однако в этом случае обе эти конверсии имеют одинаковый ранг, поэтому все равно должна быть ничья. - person cigien; 29.04.2020
comment
Если я не неправильно интерпретирую таблицу 13 в стандарте C++17, F1 требует интегрального повышения, тогда как F2 требует преобразования с плавающим интегралом. Таким образом, конверсионный ранг для F1 выше. - person BenevolentDeity; 29.04.2020
comment
Хм, я думаю, вы правы, кажется, у F2 другой ранг. - person cigien; 29.04.2020