リンクだけだとさみしいので、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/declarationによるADL回避の整理