20

n3092を見ると、§6.5.4で、範囲ベースのforループと同等であることがわかります。次に、何に等しいかを言い続け__beginます__end。それは配列と他のタイプを区別します、そして私はこれが冗長であると思います(別名混乱します)。

それは、配列タイプについて__begin__endあなたが期待するものであると言っています:最初へのポインタと最後から1つへのポインタ。次に、他のタイプの場合、__beginおよびはADLでとに__end等しくなりbegin(__range)ます。§24.6.5で定義されているを見つけるために、end(__range)名前空間stdが関連付けられています。std::beginstd::end<iterator>

ただし、との定義を見るstd::beginstd::end、これらは両方とも配列とコンテナタイプに対して定義されています。また、配列のバージョンは上記とまったく同じです。最初のポインタ、最後の1つを指すポインタです。

std::begin他のタイプに与えられた定義が同様に機能するのに、なぜ配列を他のタイプと区別する必要があるのstd::endですか?


便宜上、いくつかの要約引用符:

§6.5.4範囲ベースのforステートメント

— _RangeTが配列型の場合、begin-exprとend-exprはそれぞれ__rangeと__range + __boundです。ここで、__boundは配列のバインドです。_RangeTが不明なサイズの配列または不完全な型の配列である場合、プログラムの形式が正しくありません。

—それ以外の場合、begin-exprとend-exprはそれぞれbegin(__ range)とend(__range)であり、beginとendは引数依存のルックアップ(3.4.2)でルックアップされます。この名前空間のルックアップでは、名前空間stdは関連付けられた名前空間です。

§24.6.5範囲アクセス

template <class T, size_t N> T* begin(T (&array)[N]);

戻り値:配列。

template <class T, size_t N> T* end(T (&array)[N]);

戻り値:配列+N。

4

1 に答える 1

22

これにより、ADLのコーナーケースが回避されます。

namespace other {
  struct T {};
  int begin(T*) { return 42; }
}

other::T a[3];
for (auto v : a) {}

ADLは呼び出し時にother::beginを検出するためbegin(a)、同等のコードが壊れて、紛らわしいコンパイルエラー(T*end(a)を返すように「intをother:: T *と比較できません」の行に沿って)または異なる動作(if other :: endが定義され、同様に予期しないことをしました)。

于 2010-04-15T20:54:39.913 に答える