コンテナからイテレータを取り出す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宣言する必要がある。