読者です 読者をやめる 読者になる 読者になる

C++と色々

主にC++やプログラムに関する記事を投稿します。

ADLが謎

こちらのサイトを見て、テンプレート引数の型が宣言された名前空間も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が呼ばれる。こんなところでバグおきて欲しくないな〜… 「なんでこっちがオーバーロードされるんだよ!!バンバン!!」みたいな。 覚えといて損はない。