观察到的行为是正确的,与foo(a)
类型相关的表达式一样,根据:
14.6.2.2 Type-dependent expressions [temp.dep.expr]
1) Except as described below, an expression is type-dependent if any
subexpression is type-dependent.
2) this is type-dependent if the class type of the enclosing member
function is dependent (14.6.2.1).
3) An id-expression is type-dependent if it contains
— an identifier associated by name lookup with one or more declarations
declared with a dependent type,
...
并在 14.6.4(从属名称解析)下:
14.6.4.2 Candidate functions [temp.dep.candidate]
For a function call that depends on a template parameter, the candidate
functions are found using the usual lookup rules (3.4.1, 3.4.2, 3.4.3) except
that:
— For the part of the lookup using unqualified name lookup (3.4.1) or qualified
name lookup (3.4.3), only function declarations from the template definition
context are found.
— For the part of the lookup using associated namespaces (3.4.2), only function
declarations found in either the template definition context or the template
instantiation context are found.
If the function name is an unqualified-id and the call would be ill-formed or
would find a better match had the lookup within the associated namespaces
considered all the function declarations with external linkage introduced in
those namespaces in all translation units, not just considering those
declarations found in the template definition and template instantiation
contexts, then the program has undefined behavior.
选择“错误”是因为它是模板定义foo()
时唯一可见的,而“正确”不被考虑,因为它不在与函数参数类型关联的命名空间中。foo()
如果您修改代码以使“正确”foo()
位于关联的命名空间中,则会选择它而不是“错误” foo()
。(在这种特殊情况下,标准不允许这样做,因此请不要执行以下操作,但使用您自己的命名空间/类型,它应该是这样工作的)
#include <iostream>
#include <vector>
template<typename A> void foo(A& a)
{
std::cout << "the wrong foo" << std::endl;
}
template<typename A>
void do_stuff(A& a) {
foo(a);
}
namespace std { // evil, don't do this with namespace std!
template<typename X>
void foo(std::vector<X>& a) {
std::cout << "the right foo" << std::endl;
}
}
int main()
{
std::vector<int> q;
do_stuff(q); // calls the "right" foo()
}