模板函数查找

Dan*_*vil 7 c++ templates

考虑一下这段代码:

#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);
}

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);
}
Run Code Online (Sandbox Code Playgroud)

为什么称它为"错误的"foo?如果删除foo的第一个声明,则调用右foo.

我正在使用gcc 4.6.3.

更新: 如果按以下顺序声明函数,则调用右foo.

template<typename A> void do_stuff(A& a) { ... }
template<typename A> void foo(A& a) { ... }
template<typename X> void foo(std::vector<X>& a) { ... }
Run Code Online (Sandbox Code Playgroud)

mit*_*ull 4

观察到的行为是正确的,foo(a)根据以下内容,类型相关的表达式也是正确的:

\n\n
14.6.2.2 Type-dependent expressions                         [temp.dep.expr]\n\n1) Except as described below, an expression is type-dependent if any\n   subexpression is type-dependent.\n\n2) this is type-dependent if the class type of the enclosing member\n   function is dependent (14.6.2.1).\n\n3) An id-expression is type-dependent if it contains\n\n    \xe2\x80\x94 an identifier associated by name lookup with one or more declarations \n      declared with a dependent type,\n    ...\n
Run Code Online (Sandbox Code Playgroud)\n\n

以及第 14.6.4 条(从属姓名结果)下:

\n\n
14.6.4.2 Candidate functions                              [temp.dep.candidate]\n\nFor a function call that depends on a template parameter, the candidate\nfunctions are found using the usual lookup rules (3.4.1, 3.4.2, 3.4.3) except\nthat:\n\n\xe2\x80\x94 For the part of the lookup using unqualified name lookup (3.4.1) or qualified\n  name lookup (3.4.3), only function declarations from the template definition \n  context are found.\n\xe2\x80\x94 For the part of the lookup using associated namespaces (3.4.2), only function\n  declarations found in either the template definition context or the template\n  instantiation context are found.\n\nIf the function name is an unqualified-id and the call would be ill-formed or\nwould find a better match had the lookup within the associated namespaces\nconsidered all the function declarations with external linkage introduced in\nthose namespaces in all translation units, not just considering those\ndeclarations found in the template definition and template instantiation\ncontexts, then the program has undefined behavior.\n
Run Code Online (Sandbox Code Playgroud)\n\n

选择“错误”是因为它是模板定义时foo()唯一可见的,并且不考虑“正确” ,因为它不在与函数参数类型关联的命名空间中。foo()

\n\n

如果您修改代码以使“正确”foo()位于关联的命名空间中,则将选择它而不是“错误” foo()。(在这种特殊情况下,标准不允许这样做,所以不要执行以下操作,但使用您自己的命名空间/类型,这就是它应该如何工作)

\n\n
#include <iostream>\n#include <vector>\n\ntemplate<typename A> void foo(A& a)\n{\n    std::cout << "the wrong foo" << std::endl;\n}\n\ntemplate<typename A>\nvoid do_stuff(A& a) {\n    foo(a);\n}\n\nnamespace std { // evil, don\'t do this with namespace std!\n\ntemplate<typename X>\nvoid foo(std::vector<X>& a) {\n    std::cout << "the right foo" << std::endl;\n}\n\n}\n\nint main()\n{\n    std::vector<int> q;\n    do_stuff(q); // calls the "right" foo()\n}\n
Run Code Online (Sandbox Code Playgroud)\n