这对我来说似乎有些落后但是有效:
#include <iostream>
namespace nTest
{
struct cTest {};
void fTest(cTest& x)
{
std::cout << "nTest::fTest(cTest&) called" << std::endl;
}
}
int main(void)
{
nTest::cTest x;
fTest(x); //Weird! fTest is resolved since its parameter belongs to nTest.
return 0;
}
通常,您需要nTest ::才能访问fTest,但其属于nTest的参数似乎将nTest添加到搜索fTest的可能范围列表中。我觉得参数范围影响函数查找似乎很奇怪。
这在GCC编译得很好,但我想知道这种用法是否可移植?该范围机制的官方定义是什么?
答案 0 :(得分:13)
这是ADL(Argument Dependent Lookup)或Koenig Lookup(用于该功能的设计者)。该功能的目的是在许多情况下,相同的命名空间将包含可应用于这些类型的类型和函数,所有类型和函数都符合 interface 。如果没有ADL,则必须将标识符带入using
声明的范围,否则您必须对调用进行限定。
这成为一场噩梦,因为语言允许操作员超载。请考虑以下示例:
namespace n {
struct test {};
test operator+( test, test const & ); // implemented
};
int main() {
n::test a,b;
n::test c = a + b; //without ADL: c = n::operator+( a, b )
}
虽然看起来似乎很尴尬,但考虑n
可能是std
命名空间,test
可能是ostream
,而operator+
可能是operator<<
:
int main( int argc, char** ) {
std::cout << "Hi there, there are " << argc << " arguments" << std::endl;
}
如果没有ADL,对operator<<
的调用必须是明确的,而且你必须知道哪些是作为自由函数而不是方法实现的。您是否知道std::cout << "Hi"
正在调用自由函数而std::cout << 5
正在调用成员函数?没有多少人意识到这一点,而且严肃地说,几乎没有人关心。 ADL隐藏了你。
答案 1 :(得分:3)
它被称为Koenig aka Argument dependent lookup http://en.wikipedia.org/wiki/Argument-dependent_name_lookup
答案 2 :(得分:1)
它最初设计用于查找重载运算符,如运算符&lt;&lt;你用来发送一个字符串到std :: cout。如果我们没有ADL,您将不得不编写这样的代码:std::operator<<(std::cout, "nTest::fTest(cTest&) called")
。
不太好!
如果它适用于运营商,为什么不以相同的方式运行功能呢?