Я пытаюсь понять, как правила выбора перегрузки приводят к следующему (неинтуитивному) поведению. Когда у меня есть следующие функции:
#include <iostream>
// Overload 1
template<class T>
void write(T data)
{
std::cout << "Called write(T data)" << std::endl;
}
// Overload 2
template<class T, class ...U>
void write(T&& obj, U&&... objs)
{
std::cout << "Called write(T&& obj, U&&... objs)" << std::endl;
}
int main(int, char**)
{
int j = 0;
write(j);
return 0;
}
void write(T data) перегрузка void write(T data) Перегрузка 1). Я думаю, что это имеет смысл для меня: кандидаты на выбор перегрузки являются void write<T>(T) T = int и void write<T,U>(T&) T = int, U = <>. И write(T) и write(T&) были бы одинаково специализированными, но Overload 2 имеет пустой пакет параметров, поэтому выбирается Overload 1. Однако, если добавить третью перегрузку:
#include <iostream>
// Overload 0
void write(const int& data)
{
std::cout << "Called write(const int& data)" << std::endl;
}
// Overload 1
template<class T>
void write(T data)
{
std::cout << "Called write(T data)" << std::endl;
}
// Overload 2
template<class T, class ...U>
void write(T&& obj, U&&... objs)
{
std::cout << "Called write(T&& obj, U&&... objs)" << std::endl;
}
int main(int, char**)
{
int j = 0;
write(j);
return 0;
}
Затем внезапно появляется void write(T&& obj, U&&... objs) (перегрузка 2). Почему добавление перегрузки, которая не выбрана, изменяется, какая перегрузка действительно выбрана?
Если единственные кандидаты были void write<T,U>(T&) T = int, U = <> и void write(const int&) Я понимаю, почему выбрана void write<T,U>(T&), поэтому, возможно, что-то о добавлении дополнительной перегрузки предотвращает участие void write(T data) от выбора перегрузки? Если да, то почему?
Поскольку это, похоже, специфическое поведение компилятора, это наблюдалось на gcc 7.3.0.
Еще одно интересное поведение: если функции переупорядочиваются таким образом, что новая перегрузка помещается между исходными двумя (то есть Overload 1, Overload 0, Overload 2), то gcc отклоняет ее с call of overloaded 'write(int&) is ambiguous. Если функции переупорядочиваются так, что последняя перегрузка является последней (то есть перегрузка 1, затем перегрузка 2, затем перегрузка 0), то write(const int& data) выбрана.