模板相关的名称解析不应该找到没有链接的声明?

Template dependent name resolution should not find declarations with no linkage?

在c++标准[temp.point]中是这么写的:

The instantiation context of an expression that depends on the template arguments is the set of declarations with external linkage declared prior to the point of instantiation of the template specialization in the same translation unit.

然后在 [temp.dep.candidate]:

For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either the template definition context or the template instantiation context are found.

这是否意味着以下代码应该失败:

namespace A{
    struct S{};
}

template<class T>
void g(T a){
    f(a); //f will be found by argument dependent lookup
}

namespace A{
    static void f(S); //but f doesn't have external linkage
}

void test(A::S i){
    g(i);
}
//point of instantiation of g
//A::f(S) doesn't have external linkage 
//=> so it's not in the instantiation context of template g ??

这段代码确实编译通过了,那么这个标准段落是什么意思?

这是标准中的缺陷。最初在 core issue 561 中提出,委员会认为

Notes from the April, 2006 meeting:

The consensus of the group was [..] that internal-linkage functions should be found by the lookup (although they may result in errors if selected by overload resolution).

不幸的是,相应的修复不充分,详见 core issue 1258:

C++11 expanded the lookup rules for dependent function calls (17.7.4.2 [temp.dep.candidate] paragraph 1 bullet 2) to include functions with internal linkage; previously only functions with external linkage were considered. However, 17.7.4.1 [temp.point] paragraph 6 still says,

The instantiation context of an expression that depends on the template arguments is the set of declarations with external linkage declared prior to the point of instantiation of the template specialization in the same translation unit.

大概这个措辞被忽略了,应该与新规范协调一致。

也就是说,你引用的第二段之前的措辞是

For the part of the lookup using associated namespaces (3.4.2), only function declarations with external linkage found in either the template definition context or the template instantiation context are found.

.. 已针对 C++11 进行了修改,但该更改错过了您的第一句话,使其变得毫无意义。目的是不歧视具有内部链接的功能。