Правило устранения неоднозначности, касающееся членов и свободных операторов

#c #templates #overload-resolution #partial-orderin&

#c #шаблоны #перегрузка-разрешение #частичное упорядочение

Вопрос:

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

 class B {};

class A 
{
    template<typename T&&t; int operator (const Tamp;) const { return 1; } // Function 1
};

template<typename T, typename P&&t; int operator (const Tamp;, const Pamp;) { return 2; } // Function 2

int main()
{
    A a;
    B b;
    
    std::cout<<(a   b);

    return 0;
}
  

В этом сценарии будет вызвана функция 2. Но когда я изменяю функцию 1, чтобы она была свободной функцией вместо функции-члена

 template<typename T&&t; int operator (const Aamp;, const Tamp;) { return 1; } // Function 1
template<typename T, typename P&&t; int operator (const Tamp;, const Pamp;) { return 2; } // Function 2
  

Теперь будет вызвана функция 1, хотя в обоих случаях функция 1 в основном идентична. В чем причина этого? GCC жалуется на неоднозначность в соответствии со стандартом ISO C , но не указывает точную причину и в любом случае компилируется нормально. Этот случай уникален для операторов, поскольку их можно вызывать одинаковым образом, независимо от того, являются они членами или нет.

Ответ №1:

Теперь будет вызвана функция 1, хотя в обоих случаях функция 1 в основном идентична. В чем причина этого?

Для выбора наилучшего соответствия здесь выполняетсячастичное упорядочение шаблонов перегруженных функций.

Неофициально «A более специализирован, чем B» означает «A принимает меньше типов, чем B».

Функция 1 более специализирована, чем функция 2, поскольку она принимает меньшее количество типов; она может принимать только A в качестве своего первого операнда, в то время как функция 2 может принимать любые типы.

По той же причине в первом сценарии также должна быть выбрана функция-член 1; как это делает clan&. Похоже, это ошибка &cc, см. Ошибку 53499 и ошибку 66914.

Комментарии:

1. Я тоже так думал, но GCC выбирает функцию 2, когда функция 1 является функцией-членом, как показано здесь . Согласно ссылке, не должно быть никакой двусмысленности, как говорит GCC, и должна быть выбрана функция 1, но я предполагаю, что это просто ошибка компилятора.

2. @MrHowever Я так думаю. Исправленный ответ.