ADLとは
Argument Dependent name Lookupの略で、引数によって関数を探索する仕組みのことです。ADLは、あるオブジェクトを非メンバー関数で使用する場合に、メンバー関数と同じように簡単に使用できるようにするために存在します。
次に例を示します。名前空間Aに存在するクラスBには加算演算子の非メンバー関数が定義されています。
namespace A { class B { // class Bの定義 }; B operator+(const B&, const B&); void func(const B&); }
この加算演算子を別の名前空間で使用する場合、ADLが役に立ちます。
namespace C { void func() { B b1, b2; // ADLが使える場合。 B b3 = b1 + b2; // ADLが使えない場合。 B b4 = A::operator+(b1, b2); func(b4); // A::func(const B&)が呼び出されます。 } }
ADLの厄介なところ
とても便利なADLですが、非常に厄介な面もあります。意図しない関数が呼び出されるケースがあるからです。
namespace A { template<typename T> class B { }; } namespace C { class D { }; template<typename T> void print(T& t) { std::cout << "C::print()" << std::endl; } } int main() { A::B<C::D> b; print(b); }
上記のサンプルを実行すると、"C::print()"が出力されます。テンプレートと名前空間が組み合わさると、ADLは非常にわかりづらいバグを生み出します。
また、名前空間Aにprint関数が存在すると、コンパイル時にA::print()かC::print()のどちらを参照するべきか、曖昧であるとエラーになります。
0 件のコメント:
コメントを投稿