C++ ADL 即实参依赖查找(argument-dependent lookup), 允许调用其他命名空间中的函数。
最常见的例子为 operator<<
1 2 3 4 5 6
| #include <iostream>
int main() { operator<<(std::cout, "hello\n"); }
|
operator<< 并不存在于全局命名空间, 但左实参 std::cout 在命名空间std中, 因此找到了
std::operator<<(std::ostream&, const char*)
同理, 下面的代码也成立
1 2 3 4 5 6 7 8 9
| namespace A { class B {}; void func(const B&) {} }
int main() { A::B b; func(b); }
|
如果此时定义全局函数 void func(const A::B&) {} , 则编译器报错, 对func的调用是ambiguous
ADL 在继承中也适用, 例如
1 2 3 4 5 6 7 8 9 10 11 12
| namespace A { class B {}; void func(const B&) {} }
class C: public A::B {};
int main() { C c; func(c); }
|
有些时候我们并不希望派生类查找基类所在命名空间的函数, 来看看 boost::noncopyable 的做法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| namespace boost {
namespace noncopyable_ {
struct base_token {};
class noncopyable: base_token { #if __cplusplus < 201103L protected: noncopyable() {} ~noncopyable() {} private: noncopyable(const noncopyable&); noncopyable& operator=(const noncopyable&); #else protected: constexpr noncopyable() = default; ~noncopyable() = default; noncopyable(const noncopyable&) = delete; noncopyable& operator=(const noncopyable&) = delete; #endif };
}
typedef noncopyable_::noncopyable noncopyable;
}
|
boost::noncopyable 的作用是在C++中提供一种方案, 使得继承自该类的对象不能被拷贝(noncopyable, 顾名思义).
为了避免ADL, noncopyable 并非直接定义在 boost 中的一个类, 而是独立定义在noncopyable_, 该命名空间内没有其他函数.