Why did the range based 'for' loop specification change in C++17?
C++For LoopLanguage LawyerC++17C++ Problem Overview
I was looking over some ugly code (that was modifying the underlying sequence while iterating), and to explore the definition of the range-based for
loop, I went to cppreference.
There I noticed something strange:
The range based for
loop changed in C++17, but I do not see the reason for the change, and the code looks the same to me (just "refactored").
So the old one was:
{
auto && __range = range_expression;
for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
The new one is
{
auto && __range = range_expression;
auto __begin = begin_expr;
auto __end = end_expr;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
Why was this change made, and does it make any legal C++14 programs exhibit undefined behavior (UB) in C++17?
C++ Solutions
Solution 1 - C++
Using
auto __begin = begin_expr, __end = end_expr;
requires both begin_expr
and end_expr
to return the same type. This means you cannot have a sentinel iterator type that is different from the beginning type. Using
auto __begin = begin_expr ;
auto __end = end_expr ;
fixes that issue while proving full backwards compatibility with C++14.
Solution 2 - C++
It is explained later in the "notes":
> As of C++17, the types of the begin_expr and the end_expr do not have to be the same ...
and you can't have that with:
auto __begin = begin_expr, __end = end_expr;