用于基元类型的基于范围的

range based for used for primitive type

本文关键字:范围 于范围 类型 用于      更新时间:2023-10-16

正如在这个问题中看到的,OP试图使以下语句在数字上迭代。

for (int n : 10)
cout << n << endl;

显然,语法错误,因为int没有begin()end()方法。但这应该是可能的。基于循环的范围的文档,这一点很重要。

for(range_declaration:range _expression)loop_statement

range_expression-表示合适序列的任何表达式(定义了开始和结束成员函数或自由函数的数组或对象,请参见下文)或支撑的init列表。

以及以下

上述语法生成的代码等效于以下内容(__range__begin__end仅用于说明):

{ // until C++17
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}

begin_exprend_expr进行了澄清:

begin_exprend_expr定义如下:

  • 如果range_expression是数组类型的表达式,则[…]
  • 如果range_expression是类类型C[…]的表达式
  • 否则,begin_exprbegin(__range)end_expr则是end(__range),它们是通过参数相关查找找到的(不执行非ADL查找)

在我们的例子中,range_expression10,它既不是数组类型,也不是类类型,所以最后一个项目符号应该生效。所以我们提供这些功能

auto begin(int) {
return boost::counting_iterator<int>(0);
}
auto end(int n) {
return boost::counting_iterator<int>(n);
}

(boost::counting_iterator可以很容易地实现)。它应该起作用,对吧?但是失败了

main.cpp: In function 'int main()':
main.cpp:17:18: error: 'begin' was not declared in this scope
for (int t : 10)
^~
main.cpp:17:18: note: suggested alternatives:
main.cpp:5:6: note:   'begin'
auto begin(int) {
^~~~~
In file included from /usr/local/include/c++/7.2.0/vector:66:0,
from main.cpp:1:
/usr/local/include/c++/7.2.0/bits/range_access.h:105:37: note:   'std::begin'
template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
^~~~~

(对于end也是相同的消息)。然而,如果我根据描述更改循环的范围,我会得到以下内容,这是有效的。

{
auto && __range = 10;
for (auto __begin = begin(__range), __end = end(__range); __begin != __end; ++__begin) {
int t = *__begin;
std::cout << t << std::endl;
}
}

演示

关键短语是:

通过参数相关查找找到(不执行非ADL查找)

int没有命名空间。不,甚至连全局命名空间都没有。因此,基于名称空间的查找什么也找不到。

更具体地说,【basic.lookup.argdep】/2.1说:

如果T是一个基本类型,则其关联的命名空间和类集都是空的。

由于没有关联的命名空间或类,ADL不起作用。

通过返回计数范围的用户定义文字可以更好地处理此问题。因此,您可以键入10_rng,这将产生一个计数范围。