Разрешение перегрузки 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 выбирает эту перегрузку по сравнению с предыдущей?

Может ли кто-нибудь найти доказательства из раздела 13 стандарта об этом конкретном случае? Любая помощь или комментарий приветствуются. Спасибо!
1 2

1 ответ:

Дедукция не может быть успешной для

template <class C> void f(double, A<C,8> &var);

И аргумент типа A<int, 5>. То есть нет никакого возможного типа C, который мог бы заставить A<C,8> соответствовать типу аргумента A<int,5>. То, что преобразование возможно, не заботится о дедукции.

См. [темп.вычитать.звонок]/4. Поскольку преобразования могут быть разрешены через конструкторы преобразования, а также функции преобразования, невозможно рассмотреть (все) преобразования для вычитания типа. Это также может привести к неясностям.