入力ストリームを反復するには、通常、次のstd::istream_iteratorように使用します。
typedef std::istream_iterator<std::string> input_iterator;
std::ifstream file("myfile");
for (input_iterator i(file); i != input_iterator(); i++) {
// Here, *i denotes each element extracted from the file
}
for範囲ベースのステートメントを使用して、入力ストリームを反復処理できればいいのですが。ただし、クラス型のオブジェクトの場合、範囲ベースforでは、オブジェクトがメンバー関数を持つ必要がありbegin()ますend()(§6.5.4、太字の強調が追加されています)。
_RangeTが配列型の場合、 begin-exprとend-exprはそれぞれ と です。ここで、__rangeはバインドされた配列です。が不明なサイズの配列または不完全な型の配列である場合、プログラムの形式が正しくありません。__range + __bound__bound_RangeT
_RangeTがクラス typeである場合、unqualified-idsbeginおよびendは、クラス メンバ アクセス ルックアップ (3.4.5) によるかのように class のスコープ内で_RangeTルックアップされ、いずれか (または両方) が少なくとも 1 つの宣言、begin-exprおよびendを見つけた場合-exprはそれぞれ と です__range.begin()。__range.end()それ以外の場合、begin-exprとend-exprはそれぞれ と であり、
begin(__range)とは引数依存の検索 (3.4.2) で検索されます。この名前検索の目的で、namespaceは関連付けられた名前空間です。end(__range)beginendstd
入力ストリームにはこれらのメンバー関数がない (コンテナーではない) ため、範囲ベースは機能forしません。とにかく、抽出するタイプを指定する何らかの方法が必要になるため、これは理にかなっています (std::string上記の場合)。
しかし、抽出したいものがわかっている場合、入力ストリームに対して独自のbegin()andend()関数 (おそらく and の特殊化またはオーバーロードstd::begin())を定義std::end()して、上記のようにクラス メンバー アクセス ルックアップによって検出されるようにすることは可能でしょうか?
前のルックアップが失敗した場合、関数が引数依存のルックアップでルックアップされるかどうかは、§6.5.4 から (少なくとも私には) 不明です。考慮すべきもう1つのことは、およびその派生物には、シークのフラグであるstd::ios_baseというメンバーが既にあるということです。end
意図した結果は次のとおりです。
std::ifstream file("myfile");
for (const std::string& str : file) {
// Here, str denotes each element extracted from the file
}
または:
std::ifstream file("myfile");
for (auto i = begin(file); i != end(file); i++) {
// Here, *i denotes each element extracted from the file
}