入力ストリームを反復するには、通常、次の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)
begin
end
std
入力ストリームにはこれらのメンバー関数がない (コンテナーではない) ため、範囲ベースは機能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
}