C++ 模板函数中的名称查找规则 #包括 使用名称空间std; 模板 无效adl(T) { cout

C++ 模板函数中的名称查找规则 #包括 使用名称空间std; 模板 无效adl(T) { cout,c++,c++11,templates,C++,C++11,Templates,模板在定义点和实例化点分为两个阶段进行编译。第一阶段发生在编译器第一次处理模板定义时,一些名称立即绑定到定义。一些名称在模板实例化之前保持未绑定状态,因为它们依赖于模板参数在模板实例化并且模板参数已知之前,无法查找ER和so 在本次通话中: #include <iostream> using namespace std; template<typename T> void adl(T) { cout << "T"; } struct S { }; t

模板在定义点和实例化点分为两个阶段进行编译。第一阶段发生在编译器第一次处理模板定义时,一些名称立即绑定到定义。一些名称在模板实例化之前保持未绑定状态,因为它们依赖于模板参数在模板实例化并且模板参数已知之前,无法查找ER和so

在本次通话中:

#include <iostream>
using namespace std;

template<typename T>
void adl(T)
{
  cout << "T";
}

struct S
{
};

template<typename T>
void call_adl(T t)
{
  adl(S());
  adl(t);
}

void adl(S)
{
  cout << "S";
}

int main ()
{
  call_adl(S());
}
adl(S());
没有任何东西依赖于函数的模板参数,因此立即(在第一阶段)进行查找,并找到在该点范围内唯一名为
adl
的函数

在本次通话中:

#include <iostream>
using namespace std;

template<typename T>
void adl(T)
{
  cout << "T";
}

struct S
{
};

template<typename T>
void call_adl(T t)
{
  adl(S());
  adl(t);
}

void adl(S)
{
  cout << "S";
}

int main ()
{
  call_adl(S());
}
adl(S());

它取决于
t
的类型,因此查找延迟到
t
的类型已知时才进行实例化。当调用
call_adl(S())
时,
adl
的第二个重载在范围内,当
adl(t)时也是如此
call执行名称查找作用域中有另一个函数,它与参数更匹配。

因此编译器在第一阶段看不到“void adl(s)”的定义?@q0987否,因为它是在我移动“void adl(s)”后在
call\u adl
@user1937198的定义和实例化之间声明的'在'main'函数下面。结果仍然是'TS'。换句话说,在实例化时,'void adl(S)'还不在范围内。那么为什么结果是'TS'?[temp.point]p8“翻译单元的结尾也被认为是实例化点”,即文件中的所有声明在第2阶段都可以看到。您说过,“当
adl(t)
调用执行名称查找时,作用域中有另一个函数,它与参数更匹配。”
void adl(s)
是更好的匹配吗,因为它是一个普通的旧非模板函数?正如Herb Sutter所说,当模板函数相等匹配时,首选普通的旧非模板函数?