ADL簡易解説

リンクだけだとさみしいので、ADLの簡単な解説を書きます


ADL(Argument Dependent name Lookup)とは、引数の型によって呼び出す関数を探索する仕組みです

namespace ns {
    struct hoge {};

    void foo(const hoge& h) {}

} // namespace ns

int main()
{
    ns::hoge h;
    foo(h); // usingもusing namespaceも使わずにns::fooが呼び出せている!

    return 0;
}


名前空間内の演算子呼び出しは、この仕組みがないとできません
(できなくはないけど、==と書く代わりにstd::operator==(...)とか書かないといけない)




ADLを回避するには以下のような、特殊な名前空間に隠す方法があります

namespace ns {
    namespace hoge_ {
        struct hoge {};
    }
    using namespace hoge_;    // 方法1:usingディレクティブ(using宣言でもいい)で公開
    typedef hoge_::hoge hoge; // 方法2:typedefで公開

    void foo(const hoge& h) {}

} // namespace ns

int main()
{
    ns::hoge h;
    foo(h);     // エラー!
    ns::foo(h); // OK

    return 0;
}

あれ・・・VC++9.0だとコンパイル通っちゃうぞ。バグだ




あと、テンプレート引数の型の名前空間も探索されるので注意しましょう



そのへんはid:uskzさんが解説しています

template argumentの宣言されたnamespaceにもADLは侵入する

using-directiveによるADLの回避

using-directive/declarationによるADL回避の整理

ADL防止マクロ