遍历的输入流,我们通常会使用一个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()'将会是一个语法错误。 –