Why did the range based 'for' loop specification change in C++17?

C++For LoopLanguage LawyerC++17

C++ 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;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNoSenseEtAlView Question on Stackoverflow
Solution 1 - C++NathanOliverView Answer on Stackoverflow
Solution 2 - C++danadamView Answer on Stackoverflow