wg21.cmeerw.net

Proposed resolution (approved by CWG 2022-08-26):

Change in 13.7.4 [temp.variadic] paragraph 10 as follows:
The instantiation of a fold-expression (7.5.7 [expr.prim.fold]) produces:
  • ( ((E1 op E2 ) op . . . ) op EN ) for a unary left fold,
  • ( E1 op (. . . op (EN-1 op EN )) ) for a unary right fold,
  • ( (((E op E1 ) op E2 ) op . . . ) op EN ) for a binary left fold, and
  • ( E1 op (. . . op (EN-1 op (EN op E))) ) for a binary right fold.
...

[Accepted as a DR at the November, 2022 meeting.]

13.7.4 [temp.variadic] paragraph 10 expands a fold-expression (including its enclosing parentheses) to an unparenthesized expression. If interpreted literally, this could result in reassociation and misinterpretation of the expression. For example, given:

template<int ...N> int k = 2 * (... + N);

... k<1, 2, 3> is specified as expanding to int k<1, 2, 3> = 2 * 1 + (2 + 3); resulting in a value of 7 rather than the intended value of 12.

Further, there is implementation divergence for the following example:

#include <type_traits>
template<class ...TT>
void f(TT ...tt) {
  static_assert(std::is_same_v<decltype((tt, ...)), int&>);
}
template void f(int /*,int*/);

gcc and MSVC apply the general expression interpretation of decltype, whereas clang and icc apply the identifier special case.

Read the original on wg21.cmeerw.net ↗