Вопреки моим ожиданиям эта программа работает:
#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]
error: call to function 'do_func' that is neither
visible in the template definition nor found by
argument-dependent lookup
Таким образом, кажется, что комбинация шаблона функции и ADL необходимы для его работы.
Однако я не понимаю, почему это так ..
Это работает из-за двух интересных вещей:
Посмотри на это:
Короче, do_func
является зависимым именем, поэтому на первом этапе (когда файл только проанализировали, но шаблон функции не экземпляр) компилятор делает не решить имя do_func
, Это только проверяет синтаксис и видит, что это допустимый вызов функции. Это все. На втором этапе, когда шаблон функции создается (и, таким образом, T
известно), имя do_func
разрешен и в это время он также использует ADL для поиска имени.
Обратите внимание, что ADL работает только для пользовательских типов. Он не работает для встроенных типов, поэтому ваш второй код (т.е. func(1)
) не работает!
Других решений пока нет …