2012-08-08 101 views
9

在下面的C++代码中,首先为单个double参数定义foobar,然后再为单个参数Foo类型定义一个参数。两者都在全局命名空间内定义。从另一个命名空间访问C++全局命名空间

one名称空间内,定义了foobar的进一步重载,其中有Bar类型的单个参数。从foobar的这个版本中,带double参数(42.0)的foobar的非限定调用将失败。类似的调用foobar,这次用(::)作用域分辨率运算符进行限定,也有一个double的参数,但会成功。

另一方面,对foobar的非保留调用(具有类型Foo的参数)成功。调用foobar并使用Foo参数(由范围解析运算符进行限定)也会成功。

为什么这两种情况的行为有所不同?我使用gcc 4.7和clang ++ 3.2。

struct Foo {}; 
struct Bar {}; 

double foobar(double x) { return x; } 
Foo foobar(Foo f) { return f; } 

namespace one { 

    Bar foobar(Bar b) { 
    //foobar(42.0); // error: can't convert to Bar 
    ::foobar(42.0); 

    Foo f; 
     foobar(f); // no problem 
    ::foobar(f); 
    return b; 
    } 
}; 

回答

8

Argument dependent lookup

在调用foobar(f)函数时,将考虑Foo的命名空间。

不适用于double,因为该类型未在任何名称空间中声明。

+0

作为最后一句的补充:非限定名称查找只要找到匹配的*名称就停止,首先考虑本地范围,并且只有当它没有找到任何名称时,它才会搜索上层和全局范围。 – Xeo 2012-08-08 22:09:23

+0

谢谢博。与ADL的链接使事情变得清晰。 – user2023370 2012-08-08 22:18:39

+0

@Xeo:这是否意味着在找到foobar(Bar b)'后,调用foobar(f)'会失败? – user2023370 2012-08-08 22:39:55