自从问题(和大多数答案)发布到此缺陷报告的解决方案以来,标准已经更改。
现在,使for(:)
循环适用于您的类型的方法X
是以下两种方法之一:
和类似的const
变化。这将对实现缺陷报告更改的编译器和未实现缺陷报告的编译器都起作用。
返回的对象实际上不必是迭代器。for(:)
与C ++标准的大多数部分不同,该循环被指定为扩展为等效于:
for( range_declaration : range_expression )
变成:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr,
__end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
其中,与开头的变量__
是为了说明而已,begin_expr
并且end_expr
是一个神奇的呼叫begin
/ end
.²
对开始/结束返回值的要求很简单:必须重载pre- ++
,确保初始化表达式有效,!=
可以在布尔上下文中使用的二进制,一元*
返回可以分配赋值和初始化range_declaration
的内容,并公开析构函数。
以与迭代器不兼容的方式执行此操作可能不是一个好主意,因为如果您这样做,将来的C ++迭代可能会破坏代码。
顺便说一句,该标准的未来修订版很可能会允许end_expr
返回与类型不同的类型begin_expr
。这是有用的,因为它允许容易进行优化以使其与手写C循环一样有效的“惰性末端”评估(例如检测零终止)和其他类似优点。
¹请注意,for(:)
循环将任何临时存储在auto&&
变量中,并将其作为左值传递给您。您无法检测是否要遍历一个临时(或其他右值)。这样的重载不会被for(:)
循环。请参阅n4527的[stmt.ranged] 1.2-1.3。
²要么调用begin
/ end
方法,或ADL-仅查找的自由功能begin
/ end
,或魔术C数组的支持。请注意,std::begin
除非range_expression
返回类型为in namespace std
或与其相关的对象,否则不会调用该方法。
在 C ++ 17 范围表达式已更新
{
auto && __range = range_expression ;
auto __begin = begin_expr;
auto __end = end_expr;
for (;__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
同的类型__begin
和__end
已经分离。
这允许结束迭代器的类型与开始的类型不同。您的最终迭代器类型可以是“哨兵”,仅支持!=
begin迭代器类型。
一个为什么有用的实际示例是,当使用时,最终迭代器可以读取“检查您的代码char*
以查看是否指向'0'
” 。当在以空终止的缓冲区上进行迭代时,这允许C ++范围表达式生成最佳代码。==
char*
char*
struct null_sentinal_t {
template<class Rhs,
std::enable_if_t<!std::is_same<Rhs, null_sentinal_t>{},int> =0
>
friend bool operator==(Rhs const& ptr, null_sentinal_t) {
return !*ptr;
}
template<class Rhs,
std::enable_if_t<!std::is_same<Rhs, null_sentinal_t>{},int> =0
>
friend bool operator!=(Rhs const& ptr, null_sentinal_t) {
return !(ptr==null_sentinal_t{});
}
template<class Lhs,
std::enable_if_t<!std::is_same<Lhs, null_sentinal_t>{},int> =0
>
friend bool operator==(null_sentinal_t, Lhs const& ptr) {
return !*ptr;
}
template<class Lhs,
std::enable_if_t<!std::is_same<Lhs, null_sentinal_t>{},int> =0
>
friend bool operator!=(null_sentinal_t, Lhs const& ptr) {
return !(null_sentinal_t{}==ptr);
}
friend bool operator==(null_sentinal_t, null_sentinal_t) {
return true;
}
friend bool operator!=(null_sentinal_t, null_sentinal_t) {
return false;
}
};
没有完全C ++ 17支持的编译器中的实时示例;for
循环手动展开。
begin/end
static或free 的成员或朋友,这是可能的begin/end
。请注意放置免费功能的命名空间是什么:stackoverflow.com/questions/28242073/…–