観察された動作は正しく、次のよう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(扶養家族の名前のresoultion)の下で:
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()
}