std::beginとstd::endの使い方

コンテナからイテレータを取り出す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::vectorstd::dequestd名前空間で定義されるのでADLでbegin()end()を呼び出せるが、配列は名前空間に属さないので、ADLで呼び出せない。そのため、配列版のオーバーロードが定義されるstd名前空間だけは、using宣言する必要がある。