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 件のコメント:
コメントを投稿