#c #templates #overloading
#c #шаблоны #перегрузка
Вопрос:
Рассмотрим следующий фрагмент кода:
template<class T>
std::enable_if_t<std::is_integral<T>::value, bool> func(T value) {
std::cout << "Tn";
return func(static_cast<int64_t>(value));
}
bool func(int64_t value) {
std::cout << "int64_tn";
return true;
}
int main() {
func(1);
}
Это вызывает бесконечную рекурсию. Однако изменение порядка определения этих двух функций (если bool func(int64_t value)
они определены до шаблонной) помогает избежать этой проблемы.
Почему это? Имеет ли значение порядок перегрузки функций?
Ответ №1:
Имеет ли значение порядок перегрузки функций?
Это изменяет не результат разрешения перегрузки, а результат поиска имени; который происходит до разрешения перегрузки.
(выделено мной)
Для имени, используемого в глобальной области (пространство имен верхнего уровня), за пределами какой-либо функции, класса или объявленного пользователем пространства имен, проверяется глобальная область перед использованием имени:
Это означает, что для вызова func
внутри шаблона func
может быть найден только он сам (и добавлен в набор перегрузки), версия без шаблона вообще не будет рассматриваться.
Как вы видели, если вы измените порядок их объявления, оба func
будут найдены и рассмотрены при следующем разрешении перегрузки, и будет выбран не шаблонный func
(как и ожидалось).
Ответ №2:
Когда компилятор анализирует первую функцию (шаблон), он ничего не знает о второй перегрузке func
. Синтаксический анализ выполняется сверху вниз исходного файла.
Вот почему вам нужно иметь объявления символов, прежде чем вы их используете. Это также означает, что просто наличие объявления bool func(int64_t);
вверху решило бы вашу проблему.
Комментарии:
1. Я думаю, было бы целесообразно объяснить, почему
func
выбирается во время синтаксического анализа, а не во время создания экземпляра.
Ответ №3:
Имеет ли значение порядок перегрузки функций?
Порядок перегрузок имеет значение в том смысле, что если набор перегрузок вызывается до объявления потенциальной перегрузки, эта еще не объявленная функция не участвует в разрешении перегрузки.
Порядок перегрузок, объявленный перед вызовом функции, не имеет значения.