Разрешение перегрузки C++ неоднозначно-GCC
Я пытаюсь понять, почему GCC выбирает f(char, A<C, 5> &var)
для разрешения перегрузки в коде ниже:
template <class C, int N> struct A { };
template <class C> struct A<C, 8> { static_assert(sizeof(C) > 8, "Assertion in A<C,8>"); };
template <class C> struct A<C, 5> { static_assert(sizeof(C) < 8, "Assertion in A<C,5>"); operator A<C,8>&(); };
template <class C> void f(double, A<C,8> &var);
template <class C> void f(char, A<C,5> &var);
int main(void)
{
A<int, 5> a;
f(4., a);
}
Есть две доступные перегрузки:
template <class C> void f(double, A<C,8> &var);
4.
точные соответствия double
(не требуется неявное преобразование), но для второго параметра требуется пользовательское преобразование. Так вот эта перегрузка: exact match
& user-define conversion
Следующая перегрузка, которой соответствует GCC:
template <class C> void f(char, A<C,5> &var);
4.
требуется неявное преобразование в char
, но точное соответствие для A<C,5>
. Есть ли какая-то причина, почему GCC выбирает эту перегрузку по сравнению с предыдущей?
1 ответ:
Дедукция не может быть успешной для
template <class C> void f(double, A<C,8> &var);
И аргумент типа
A<int, 5>
. То есть нет никакого возможного типаC
, который мог бы заставитьA<C,8>
соответствовать типу аргументаA<int,5>
. То, что преобразование возможно, не заботится о дедукции.См. [темп.вычитать.звонок]/4. Поскольку преобразования могут быть разрешены через конструкторы преобразования, а также функции преобразования, невозможно рассмотреть (все) преобразования для вычитания типа. Это также может привести к неясностям.