3

I've opened a bug to GCC, but I'd like to know if I'm right in my expectations.

Consider this proposal and the following fold expression:

(args < ...)

It should be equivalent to:

((args$0 < args$1) < ...) < args$n

Consider the following code:

#include <cassert>
int main() {
    assert((0 < 42) < 3);
}

The assert compiles and works properly, it doesn't fail (as expected indeed, note that the result is not ((0 < 42) and (42 < 3)), the expression itself is quite unusual and meaningless).
On the other side, when using a fold expression:

template<int... I>
static constexpr bool f() {
    return (I < ...);
}

int main() {
    static_assert(f<0, 42, 3>(), "!");
}

The assert fails at compile time (GCC 6.1.0).
I'd expect it to compile because of what contained in the proposal.
It should succeed for it is equivalent to the example above that doesn't involve fold expressions.
The unpacked expression should be indeed: ((0 < 42) < 3).

Am I right or I'm missing something important here about fold expressions?

Leon
  • 31,443
  • 4
  • 72
  • 97
skypjack
  • 49,335
  • 19
  • 95
  • 187
  • 1
    The way I like to remember this is that "`(std::cout << ... << x)` should do the right thing" (i.e., a left fold). Then take out the `std::cout` and `(... op x)` is a left fold too. – T.C. Jun 11 '16 at 16:12

1 Answers1

4

N4191 was the original proposal. GCC's C++1z status page notes that it implement the revised proposal in N4295.

The rules for left and right folds changed, and I believe your code is now required to produce a right fold, i.e. 0 < (42 < 3), which is false.

I < ... is a right fold; ... < I would be a left fold.

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64