什么是ADL
ADL(Argument Dependent Lookup),参数依赖查找,明确的意思是依赖参数的函数查找,即对于函数调用,不仅会依照常规的名称查找规则,还会在函数参数所在的命名空间内查找
我们常用的 std::cout << “…” 其实就是一个 ADL 的例子,std::cout,查看一下 STL 的代码,它是
std::basic_ostream<char, std::char_traits<char>>
而这个类只定义了针对算术类型和指针类型的 operator<< 并没有定义针对 const char * 的版本,使用编译器的跳转功能跳转到 << 的调用,其实是
template<class _Traits>
std::basic_ostream<char, _Traits> operator<<(std::basic_ostream<char, _Traits> &, const char *)
也就是说这个调用其实等价于:
operator<<(std::cout, "...")//注意operator<<前并没有使用std::来指定查找位置
这个对于 std::operator<< 的调用能顺利解析而不会触发 ‘没有与操作数匹配的操作符’ 错误,正是由于ADL发挥了作用:第一个参数 std::cout 所在的命名空间 std 被加入到对 operator<< 的查找空间内,从而匹配到针对 const char * 的 operator<<
ADL+模板
当函数参数是模板时,查找空间会扩展到参数模板所在的命名空间以及模板实参的命名空间:
折叠代码
namespace space
{
struct A{};
template<typename T> struct TpA{};
template<typename T, template<typename> class Tp>
void foo(Tp<T> &){}
}
template<typename T> struct TpB{};
space::TpA<int> tai;
foo(tai);//通过TpA找到foo
TpB<space::A> tba;
foo(tba);//通过A找到foo
根据模板实参自动选择调用函数
ADL+模板很容易就能实现根据模板实参调用不同函数的功能:
折叠代码
namespace spaceA
{
struct A{};
void foo(A &){}
}
namespace spaceB
{
struct B{};
void foo(B &){}
}
...
template<typename T> void dispatch(T &value)
{
foo(value);
}
spaceA::A a;
dispatch(a);//绑定到spaceA::foo(spaceA::A &)
spaceB::B b;
dispatch(b);//绑定到spaceB::foo(spaceB::B &)
只要约定好接口,dispatch函数就能根据实例化类型来调用,可以实现松散的代码结构,并且函数的绑定在编译期进行,继承体系也能实现相同的需求,但是函数的调用是运行时解析。可以根据实际情况决定选用哪种方案。
来源链接:https://www.cnblogs.com/saltymilk/p/18853435
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
暂无评论内容