0

Chapter 3 : A Tour of C++: Abstraction Mechanisms のドラフトの 82 ページで、著者は次のように書いています。

Vectorに range-for ループも使用する場合は、適切なbegin()およびend()関数を定義する必要があります。

template<typename T>
T∗ begin(Vector<T>& x)
{
    return &x[0]; // pointer to first element
}

template<typename T>
T∗ end(Vector<T>& x)
{
    return x.begin()+x.size(); // pointer to one-past-last element
}

それらを考えると、次のように書くことができます。

void f2(const Vector<string>& vs) // Vector of some strings
{
    for (auto s : vs)
        cout << s << ’\n’;
}

クラス テンプレートVectorがドラフトの 81 ページで定義されていることに注意してください。

4

3 に答える 3

5

範囲ベースの for が機能するためには、コンパイラは反復子を取得するための適切な関数を見つける必要があります。

これが、範囲ベースの for が C 配列で機能する理由です。明らかに、配列はメンバー関数を持つことができないため、標準ライブラリはこれと同様に定義された 2 つの関数を提供します。

template<typename T, size_t N>
T* begin( T(&array)[N] )
{
    return array;
}

についても同様ですend

タイトルからあなたの質問に答えるには: それらは可能ですが、必須ではありません。クラスと同じ名前空間で無料の関数を定義すると、それらが見つかります。

于 2013-08-01T12:52:20.757 に答える
4

.begin()配列またはコンテナでない場合は、引数に依存する name.end()で検索します。

それはここで言われています:

範囲ベースの次の事実に注意してください。

  • 配列を自動的に認識します。

  • .begin() と .end() を持つコンテナーを認識します。

  • それ以外の場合は、引数依存のルックアップ begin() および end() を使用します。

于 2013-08-01T12:52:12.047 に答える
2

このような範囲では、次のことに基づいています。

for ( for-range-declaration : expression ) statement

標準では、expression がクラス型の場合、コンパイラはメンバ ( (expression).begin()(expression).end()) または自由関数 ( begin((expression))、 )を探すと規定されています。end((expression))

したがって、メンバー関数またはフリー関数(引数依存のルックアップのスコープ内にある必要があります) を提供できます。

C++11、§ 6.5.4 [stmt.ranged]

これは、標準に従って範囲ベースの for が行うことです。

for ( for-range-declaration : expression ) statement

range-init = ( expression )

{
  auto && __range = range-init;
  for ( auto __begin = begin-expr,
    __end = end-expr;
    __begin != __end;
    ++__begin ) 
  {
    for-range-declaration = *__begin;
    statement
  }
}

begin-exprとは次のend-exprように説明されます。

  • _RangeTが配列型の場合、 begin-exprend-expr_rangeでありそれぞれ_range + _bound ここで_boundはバインドされた配列です。_RangeTが不明なサイズの配列または不完全な型の配列である場合、プログラムは不正な形式です。

  • がクラス型である場合_RangeT、非修飾 ID の begin および end は、クラス メンバー アクセス ルックアップ (3.4.5) によるかのようにクラス _RangeT のスコープでルックアップされ、いずれか (または両方) が少なくとも 1 つの宣言、beginexpr およびend-expr はそれぞれ __range.begin() と __range.end() です。

  • それ以外の場合、begin-exprend-exprはそれぞれ と であり、begin(__range)とは引数依存の検索 (3.4.2) で検索されます。この名前検索の目的で、名前空間 std は関連付けられた名前空間です。end(__range)beginend

于 2013-08-01T12:58:56.490 に答える