Почему в С++ 17 изменилась спецификация цикла, основанная на диапазоне "для"?

Я просматривал некрасивый код (который изменял основную последовательность во время итерации), и чтобы изучить определение цикла for, основанного на диапазоне, я перешел к cppreference.

Там я заметил что-то странное:

Цикл, основанный на диапазоне for, изменен в С++ 17, но я не вижу причины этого изменения, и код выглядит для меня так же (просто "рефакторинг"). Итак, старый был:

{
  auto && __range = range_expression;
  for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {
    range_declaration = *__begin;
    loop_statement
  }
} 

Новый -

{
  auto && __range = range_expression;
  auto __begin = begin_expr;
  auto __end = end_expr;
  for ( ; __begin != __end; ++__begin) {
    range_declaration = *__begin;
    loop_statement
  }
} 

Почему было сделано это изменение, и заставляет ли оно какие-либо законные программы на С++ 14 демонстрировать неопределенное поведение (UB) на С++ 17?

Ответ 1

Использование

auto __begin = begin_expr, __end = end_expr;

требует, чтобы begin_expr и end_expr возвращали один и тот же тип. Это означает, что вы не можете иметь тип итератора, который отличается от начального типа. Использование

auto __begin = begin_expr ;
auto __end = end_expr ;

исправляет эту проблему, обеспечивая полную обратную совместимость с С++ 14.

Ответ 2

Это объясняется позже в "заметках":

Начиная с С++ 17, типы begin_expr и end_expr не обязательно должны быть одинаковыми...

и вы не можете иметь это с:

auto __begin = begin_expr, __end = end_expr;