こちらのサイトを見て、テンプレート引数の型が宣言された名前空間もADLの範囲にはいるんだー、へー、と思った。
ADLはAgument Dependent Lookupの略で、実引数依存の名前検索と訳されている。要は、ある名前空間に所属している関数・演算子のオーバーロードを使うとき、
引数の値の型が宣言された名前空間も関数・演算子のオーバーロード捜すときの範囲に含まれるから、わざわざ(名前空間)::(関数名)とか、
(名前空間)::operator(何か)とか書かなくていいね、やったね便利!って感じ。
で、リンク先様のソースとまったく一緒でわざわざ書く必要もあるのか疑問ですが、サンプルソースを出すと…
#include <iostream> using std::cout; using std::endl; namespace a { struct hoge{}; template<class T> void func(T&){cout << "a::func" << endl;} } namespace b { template<class T> struct foo{}; template<class T> void func(const T&){cout << "b::func<T>" << endl;} } int main() { b::foo<a::hoge> f; func(f); }
実行結果
a::func 続行するには何かキーを押してください . . .
関数funcは名前空間aとbで合計2つオーバーロードされている。funcの引数はfoo型で、foo型は名前空間bに所属しているので、名前空間bのfuncが呼ばれると思うが(と期待したいが)、実行結果を見ればわかるが名前空間aのfuncが呼ばれている。
fooはテンプレートクラス型で、テンプレート引数にa::hoge型を指定している。こうすることで、foo型を引数に取る関数はfooが宣言された名前空間bだけではなく、名前空間aも検索対象になっている。フッシギー!
funcを呼ぶときちゃんとb::funcと明示してあげればb::funcが呼ばれる。こんなところでバグおきて欲しくないな〜… 「なんでこっちがオーバーロードされるんだよ!!バンバン!!」みたいな。 覚えといて損はない。