Почему компилятор находит мою функцию, если она еще не объявлена?

Вопреки моим ожиданиям эта программа работает:

#include <iostream>namespace a { struct item{}; }
namespace b { struct item{}; }template<typename T>
void func(T t) { do_func(t); }int main()
{
func(a::item{});
func(b::item{});
}namespace a { void do_func(item) { std::cout << "a::func\n"; } }
namespace b { void do_func(item) { std::cout << "b::func\n"; } }

Выход:

a::func
b::func

Проверки с онлайн-компиляторами:

Если инстанция func<T> происходит в организме main тогда я бы ожидал, что a::do_func а также b::do_func еще не объявлены.

Как это может работать?

Обновить

Согласно @Marc Claesen, причина, по которой вышеперечисленные работы:

Создание шаблона выполняется после прочтения всего исходного кода.

Тем не менее, тогда почему этот код делает не Работа:

#include <iostream>

template<typename T>
void func(T t) { do_func(t); }

int main()
{
func(1);
}

void do_func(int) { std::cout << "do_func(int)\n"; }

Увидеть НКУ-4,8:

error: 'do_func' was not declared in this scope,
and no declarations were found by argument-dependent
lookup at the point of instantiation [-fpermissive]

лязг ++ 3.4:

error: call to function 'do_func' that is neither
visible in the template definition nor found by
argument-dependent lookup

Таким образом, кажется, что комбинация шаблона функции и ADL необходимы для его работы.

Однако я не понимаю, почему это так ..

16

Решение

Это работает из-за двух интересных вещей:

  • поиск по двухфазному имени который выполняется для поиска зависимый имена.
  • и Аргумент-зависимый поиск (ADL).

Посмотри на это:

Короче, do_func является зависимым именем, поэтому на первом этапе (когда файл только проанализировали, но шаблон функции не экземпляр) компилятор делает не решить имя do_func, Это только проверяет синтаксис и видит, что это допустимый вызов функции. Это все. На втором этапе, когда шаблон функции создается (и, таким образом, T известно), имя do_func разрешен и в это время он также использует ADL для поиска имени.

Обратите внимание, что ADL работает только для пользовательских типов. Он не работает для встроенных типов, поэтому ваш второй код (т.е. func(1)) не работает!

14

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]