模板函数查找 [英] Template function lookup

查看:25
本文介绍了模板函数查找的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这段代码:

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

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

Why is it calling the "wrong" foo? If the first declaration of foo is removed the right foo is called.

我使用的是 gcc 4.6.3.

I am using gcc 4.6.3.

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

Update: If functions are declared in the following order, the right foo is called.

template<typename A> void do_stuff(A& a) { ... }
template<typename A> void foo(A& a) { ... }
template<typename X> void foo(std::vector<X>& a) { ... }

推荐答案

观察到的行为是正确的,因为 foo(a) 是一个类型依赖表达式,根据:

The observed behavior is correct, as foo(a) is a type dependent expression according to:

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(从属名称解析):

and under 14.6.4 (Dependent name 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() 不被考虑,因为它不在与函数参数类型相关的命名空间.

The "wrong" foo() is picked because that's the only one visible at the point of template definition, and the "right" foo() is not considered because it's not in a namespace associated with the types of the function arguments.

如果您修改代码以使正确的"foo() 位于关联的命名空间中,则会选择它而不是错误的"foo().(在这种特殊情况下,标准不允许这样做,因此不要执行以下操作,但是对于您自己的命名空间/类型,这应该是它的工作方式)

If you modify your code so that the "right" foo() would be in an associated namespace, it would be picked instead of the "wrong" foo(). (In this particular case, it's not allowed by the standard, so don't do the below, but with your own namespace / types this is how it should work)

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

这篇关于模板函数查找的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆