Разрешение перегрузки 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. Поскольку преобразования могут быть разрешены через конструкторы преобразования, а также функции преобразования, невозможно рассмотреть (все) преобразования для вычитания типа. Это также может привести к неясностям.