ADLに関して、優先度がどれくらい高いのか実際にコードを書いてみました。
ネットを探せば答えがありそう(というかwikiに答えが載ってました)ですが、自学のためにもコーディング・・・。
なお、ADLとはなんぞや?については参考をみてください。
コード
結論的にはこれなんですが。。。
namespace hoge{
struct X{
int a[100];
};
int * begin(X& x) {
std::cout << "hoge::begin()" << std::endl;
return x.a;
}
int * end(X& x) { return x.a+100; }
}
template < typename Container >
void f(Container && c)
{
using std::begin;
using std::end;
auto iter = begin(c);
auto enda = end(c);
}
int main(int argc, char* argv[])
{
std::vector<int> v = { 1, 2, 3, 5 };
std::cout << "vector" << std::endl;
f(v);
int ar[] = { 1, 2, 3, 5 };
std::cout << "array" << std::endl;
f(ar);
hoge::X a;
std::cout << "namespace hoge" << std::endl;
f(a);
return 0;
}
結果
vector
array
namespace hoge
hoge::begin()
て具合でhoge名前空間内のbeginが呼ばれてます。
つまり上記コードの関数fは、
- std名前空間で定義されているコンテナはstd::begin、std::endを使い、
- 配列のときもstd::begin、std::endを使い、
- 任意名前空間で定義したbegin、endがあれば、それを使う。 というテンプレート関数になります。
なので当然、関数f内の
using std::begin;
using std::end;
を削除すると、int ar[]が引数のときにbegin/endの未定義でエラーですし、
auto iter = std::begin(c);
auto enda = std::end(c);
と書くと、任意名前空間で定義したbegin、endは呼ばれなくなります。
まとめ
using で定義するよりもADLが優先される。