针对模板的有限和无限定名称查找的不同行为 [英] Different behavior for qualified and unqualified name lookup for template

查看:100
本文介绍了针对模板的有限和无限定名称查找的不同行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码应如何运行?如果在 call_read()函数中使用限定名称,则调用忽略我的重载的泛型函数;如果我使用非限定名称,它会先调用重载,然后调用通用版本。有什么不同?这是GCC中的错误吗?

How should this code behave? It calls generic function ignoring my overload if I use qualified name in call_read() function; and it calls overload first and then generic version if I use unqualified name. What's the difference? Is it a bug in GCC?

#include <iostream>

struct info1 {};
struct info2 {};

template<class T> void read(T& x)
{
   std::cout << "generic" << std::endl;
}

template<class T> void call_read(T& x)
{
   ::read(x); // if I replace ::read(x) with read(x) the overload is called
}

void read(info1& x)
{
   std::cout << "overload" << std::endl;
}

int main()
{
   info1 x;
   info2 y;
   call_read(x);
   call_read(y);
}



我还注意到它对基本类型的工作不同。
查看下面的代码

I also noticed that it works different for fundamental types. See the code bellow

#include <iostream>

typedef struct info1 {};
typedef struct info2 {};
typedef int info3;
typedef double info4;

template<class T> void read(T x)
{
    std::cout << "generic" << std::endl;
}

template<class T> void call_read(T x)
{
    read(x);
}

void read(info1 x)
{
    std::cout << "overload" << std::endl;
}
void read(info3 x)
{
    std::cout << "overload" << std::endl;
}

int main()
{
    call_read(info1());
    call_read(info2());
    call_read(info3());
    call_read(info4());
}

它应该调用重载函数两次,但不是。
查看结果
http://codepad.org/iFOOFD52

It is supposed to call overloaded function twice, but it's not. See the result here http://codepad.org/iFOOFD52

推荐答案

您观察到的是两相名称查找 / em>。

What you're observing is a superposition of two-phase name lookup and argument dependent lookup.

让我们看看标准说的是什么(C ++ 03)。 [temp.dep]:

Let's see what the standard says (C++03). [temp.dep]:


[...]在表单中:

[...] In an expression of the form:

postfix-expression ( expression-listopt )

其中postfix-expression是标识符,当且仅当表达式列表中的任何表达式是类型依赖表达式(14.6.2.2)时,标识符表示依赖名称。

where the postfix-expression is an identifier, the identifier denotes a dependent name if and only if any of the expressions in the expression-list is a type-dependent expression (14.6.2.2).

这意味着在 :: read read 是一个依赖名称,因为 x 是类型相关的。这意味着它在实例化的时候解决。让我们看看这个[temp.dep.candidate]的规则是什么:

That means that in both read and ::read, read is a dependent name because x is type-dependent. That means that it's resolved at the point of instantiation. Let's see what are the rules for this [temp.dep.candidate]:


对于依赖于模板参数的函数调用,if函数名是一个非限定id而不是一个模板id,使用通常的查找规则(3.4.1,3.4.2)找到候选函数,除了:

For a function call that depends on a template parameter, if the function name is an unqualified-id but not a template-id, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:

- 对于使用非限定名称查找(3.4.1)的查找部分,仅找到具有模板定义上下文的外部链接的函数声明。

— For the part of the lookup using unqualified name lookup (3.4.1), only function declarations with external linkage from the template definition context are found.

因此对于 :: read 情况,只考虑在模板定义之前声明的函数。但是:

Therefore for the ::read case only functions declared before the template definition are considered. But:


- 对于使用关联命名空间(3.4.2)的查找部分,在模板定义上下文或模板实例化上下文中找到外部链接。

— 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.

用于不合格的 read 两个函数,它们在模板定义和模板实例化时可见。

for the unqualified read both functions are considered, those visible at template definition and template instantiation.

这篇关于针对模板的有限和无限定名称查找的不同行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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