范围基于用于原始类型

Zer*_*ges 3 c++ language-lawyer c++14

正如在这个问题中看到的那样,OP试图让以下语句迭代数字.

for (int n : 10)
    cout << n << endl;
Run Code Online (Sandbox Code Playgroud)

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

for ( range_declaration : range_expression ) loop_statement

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

和以下

上述语法产生码等效于以下(__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
    }
}
Run Code Online (Sandbox Code Playgroud)

澄清begin_exprend_expr是:

begin_exprend_expr定义如下:

  • 如果range_expression是数组类型的表达式,那么[...]
  • 如果range_expression是类类型C [...]的表达式
  • 否则,begin_exprbegin(__range)end_exprend(__range),它们通过参数相关的查找实测值(非ADL查找不执行).

在我们的例子中,range_expression10,不是数组类型,也不是类类型,所以最后一个子弹应该生效.所以我们提供这些功能

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

auto end(int n) {
    return boost::counting_iterator<int>(n);
}
Run Code Online (Sandbox Code Playgroud)

(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>&);
                                     ^~~~~
Run Code Online (Sandbox Code Playgroud)

(和相同的消息end).但是,如果我根据描述更改基于范围的for循环,我会得到以下,这是有效的.

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

DEMO

Nic*_*las 8

关键词是:

通过参数依赖查找找到的(不执行非ADL查找)

int没有命名空间.不,甚至不是全局命名空间.因此,基于命名空间的查找找不到任何内容.

为了更具体的规范,[basic.lookup.argdep] /2.1说:

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

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

这将由返回计数范围的用户定义的文字更好地处理.所以你要键入10_rng,这将产生一个计数范围.