Разрешение перегрузки, порядок определенных функций и шаблонов

#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:

Имеет ли значение порядок перегрузки функций?

Порядок перегрузок имеет значение в том смысле, что если набор перегрузок вызывается до объявления потенциальной перегрузки, эта еще не объявленная функция не участвует в разрешении перегрузки.

Порядок перегрузок, объявленный перед вызовом функции, не имеет значения.