Перегруженная функция не всегда выбирается перед созданием шаблона
Я создал некоторый код, который использует шаблон функции и перегрузку (не специализацию) этой функции. Когда я вызываю функцию с объектом класса, который является производным от параметра в ней, он использует шаблон, что приводит к ошибке компиляции. Я читал http://www.gotw.ca/publications/mill17.htm и у меня сложилось впечатление, что перегруженные функции всегда будут иметь преимущество перед шаблонами. Я создал похожий пример бездействия:
class ITest
{
public:
virtual void foo()=0;
};
class TheTest:public ITest
{
public:
virtual void foo()
{
}
};
class test
{
public:
template<typename T>
void handle(T par)
{
par++;
}
void handle(ITest &t)
{
t.foo();
}
};
void TestThem()
{
test t;
t.handle(2);
t.handle(3.0);
TheTest t2;
t.handle(t2);
}
Я бы ожидал t.handle(t2)
называть перегруженным void handle(ITest &t)
поскольку TheTest
происходит от ITest
, Однако компилятор выбирает шаблон, который генерирует ошибку. Когда я меняю void handle(ITest &t)
в void handle(TheTest &t)
он компилируется нормально.
Я исправил это, удалив функцию шаблона и перегрузив все используемые типы, но это обременительно, поскольку все они делают одно и то же.
1 ответ
У меня сложилось впечатление, что перегруженные функции всегда будут иметь преимущество перед шаблонами.
Это верно, но только в том случае, если не шаблонная функция и шаблонная функция одинаково хороши. В этом случае используется не шаблонная функция.
В этом случае, хотя они не одинаково хороши. t2
это TheTest
при запуске разрешения перегрузки находит void handle(ITest &t)
а также void handle(TheTest par)
(Я создал экземпляр шаблона здесь). Так как версия шаблона даст точное совпадение, это лучшая функция и она выбрана.
Способ исправить это - ограничить шаблон работой только для типов, которые не являются производными от ITest
, Если вы измените функцию шаблона на
template<typename T, std::enable_if_t<!std::is_base_of_v<ITest, T>, bool> = true>
void handle(T par)
{
par++;
}
Тогда он будет вызываться только для типов, которые не являются производными от ITest
, Вы можете увидеть, как это работает в этом живом примере.