コンテナからイテレータを取り出すstd::begin()関数とstd::end()関数は、テンプレート外では名前空間修飾を付けて呼び出す使い方でいいが、テンプレート内で使用する場合は、using宣言した上で名前空間修飾なしに呼び出す必要がある。(std::swap()と同じ)
#include <iterator> template <class Range> void f(const Range& r) { using std::begin; using std::end; auto first = begin(r); auto last = end(r); // use first, last... } #include <vector> int main() { std::vector<int> v = {1, 2, 3}; int ar[] = {4, 5, 6}; f(v); f(ar); }
これは、標準外で定義されるbegin()/end()関数を考慮するため。
標準外では、begin()/end()メンバ関数を持っていないコンテナのための非メンバ関数版begin()/end()関数が定義される。そのため、これらの非メンバ関数は、名前空間修飾をせず、ADLで呼び出す。
std名前空間のbegin()/end()をusing宣言しているのは、配列版を考慮するため。std::vectorやstd::dequeはstd名前空間で定義されるのでADLでbegin()/end()を呼び出せるが、配列は名前空間に属さないので、ADLで呼び出せない。そのため、配列版のオーバーロードが定義されるstd名前空間だけは、using宣言する必要がある。