基于范围的循环和范围类型

时间:2019-07-25 05:52:51

标签: c++ for-loop c++17

参考Range-based for loop

下提到的以下文本片段
  

如果range_expression是类类型C的表达式,且同时具有   名为begin的成员和名为end的成员(无论类型是   该成员的可访问性),则begin_expr为__range.begin(),   end_expr是__range.end();

     

如果范围类型具有名为的成员,则使用成员解释   开始,一个名为end的成员。不论是否   member是类型,数据成员,函数或枚举数,无论   其可访问性。因此,像喵喵类这样的类{枚举{begin = 1,   end = 2}; / *课程的其余部分* /};不能与基于范围的   即使存在命名空间范围的开始/结束功能,for循环也是如此。

理解是否正确,开始和结束应该仅是范围类型(​​可能返回迭代器类型)的成员函数的名称?好奇地了解缺乏针对此约束的任何解决方法的技术原因。

2 个答案:

答案 0 :(得分:4)

您需要提供可以通过argument-dependent lookup找到的非成员beginend函数(或其他可调用对象),或显式地具有成员函数(或可调用对象)分别命名为beginend,它们不带参数,并且返回类似迭代器的对象(即,它们应支持后缀++和取消引用*,当然可以使用==

由于“技术原因”,这是因为基于范围的for循环只是普通迭代器for循环的语法糖。并且编译器必须知道调用“ begin”和“ end”迭代器的函数。

答案 1 :(得分:3)

  

理解是否正确,开始和结束应该仅是范围类型(​​可能返回迭代器类型)的成员函数的名称?

否;实际上,即使它们不是成员函数,大多数也完全可以用作开始/结束迭代器对!

这里是一个使用数据成员的人:

struct A {
  A() : begin([this] { return array; }), end([this] { return array + 3; }) {}

  int array[3];
  std::function<int*()> begin;
  std::function<int*()> end;
};

枚举器没有任何意义,并且无法通过.访问类型。命名类型或带有beginend的枚举数的类型应该是非常稀有的,这可能就是为什么没有引入不排除枚举数的特殊规则的原因。