可以在不使用模板的情况下向我展示ADL的示例吗?从来没有见过这样的东西。我的意思是here。具体来说,我感兴趣的例子就是它会导致一些陷阱,如上所述。
修改
我认为Tomalak的答案可以扩展到陷阱。考虑一下:
namespace dupa {
class A {
};
class B : public A {
public:
int c;
B() {
}
};
void f(B b) {
printf("f from dupa called\n");
}
}
void f(dupa::A) {
printf("f from unnamed namespace called\n");
}
int main()
{
dupa::B b;
f(b);
return 0;
}
这里我们希望调用来自未命名的命名空间的f,而不是调用另一个。
答案 0 :(得分:4)
我无法向您展示导致陷阱的事情,但我可以展示ADL working without templates:
namespace foo {
struct T {} lol;
void f(T) {}
}
int main() {
f(foo::lol);
}
请注意,lol
的类型必须是class-type
;我最初尝试使用内置功能,如您所见,但它无效。
答案 1 :(得分:2)
引起混淆的诀窍是创建一个场景,其中函数的参数是可互换的或可转换的,并且ADL可能选择可能不是您期望的东西。我不确定这是令人印象深刻还是预期:
namespace a {
struct A {};
void f( A* ) { std::cout << "a::f" << std::endl; }
}
namespace b {
struct B : ::a::A {};
void f( B* ) { std::cout << "b::f" << std::endl; }
}
void test() {
f( new b::B ); // b::f
a::A* p = new b::B;
f( p ); // a::f
}
类型相同,但ADL将检查参数的静态类型并将该命名空间添加到搜索中。这反过来意味着确切的静态类型可能使编译器可以看到不同的函数。当有多个参数可以应用ADL或重载决策时,事情可能会更加混乱。
答案 2 :(得分:2)
没有模板 使用swap(),因为这是最常见的用法。
#include <iostream>
namespace One
{
class A {};
void swap(A& lhs, A& rhs) { std::cout << "Swap-One A\n";}
}
namespace Two
{
class A {};
void swap(A& lhs, A& rhs) { std::cout << "Swap-Two A\n";}
}
int main()
{
One::A oneA_l;
One::A oneA_r;
Two::A twoA_l;
Two::A twoA_r;
swap(oneA_l, oneA_r);
swap(twoA_l, twoA_r);
}