遍歷的輸入流,我們通常會使用一個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,粗體強調):
if
_RangeT
is an array type, begin-expr and end-expr are__range
and__range + __bound
, respectively, where__bound
is the array bound. If_RangeT
is an array of unknown size or an array of incomplete type, the program is ill-formed;if
_RangeT
is a class type, the unqualified-idsbegin
andend
are looked up in the scope of class_RangeT
as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, begin-expr and end-expr are__range.begin()
and__range.end()
, respectively;otherwise, begin-expr and end-expr are
begin(__range)
andend(__range)
, respectively, wherebegin
andend
are looked up with argument-dependent lookup (3.4.2). For the purposes of this name lookup, namespacestd
is an associated namespace.
該輸入流不具有這些成員函數(他們不是容器),所以基於範圍的for
不適用於他們。無論如何,這是有道理的,因爲您需要某種方式來指定要提取的類型(在上面的情況下爲std::string
)。
但是,如果我們知道我們要提取,是不是可以定義我們自己begin()
和end()
功能(可能是專業化或std::begin()
和std::end()
過載),用於輸入流,使得他們將類成員訪問查找爲找到如上所述?
從§6.5.4中不清楚(至少對我來說)如果以前的查找失敗,函數是否會隨參數查找而被查找。另一件要考慮的事情是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
}
這僅僅是我,還是從規格來說還不清楚?如果'_RangeT'不是數組或類的類型,'std :: begin()'和'std :: end()'似乎就會被找到。 –
是的,這不是最好的措辭,但我認爲你打算把它看作是「如果它是一個類,它有.begin和.end那麼它將使用那些...否則」,即你可以提供免費的功能。 –
「*'begin'和'end'在類_RangeT ...的範圍內查找,如果**發現至少有一個聲明**,則」begin-expr「和」end-expr「爲'__range.begin()'和'__range.end()'*「 - 因爲'std :: ios_base :: end'確實存在(因此會找到'std :: ifstream :: end')遊戲結束。 '.begin()'不會被發現,'.end()'將會是一個語法錯誤。 –