https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122903

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Actually, the iterator type is fine, but the predicate being passed to
std::all_of is non-conforming. [algorithms.requirements] says:

"If an algorithm takes Predicate pred as its argument and first as its iterator
argument
with value type T, the expression pred(*first) shall be well-formed and the
type decltype(pred(*first)) shall model boolean-testable (18.5.2). The function
object pred shall not apply any non-constant function through its argument.
Given a glvalue u of type (possibly const) T that designates the same object as
*first, pred(u) shall be a valid expression that is equal to pred(*first)."

So pred(arg) is required to work even if arg is a const lvalue, so it's not a
valid predicate if it can only be called with an rvalue. That's the case here,
because it wants to initialize an argument of move-only type.

So your fix to gjs is correct, it makes the predicate work with lvalues of the
OwnedInfo type.

It's intentional that the call wrappers in bits/predefined_ops.h do *not*
forward their arguments:

  // These aren't fully "transparent" like std::less<void> because they
  // do not use perfect forwarding, everything is treated as an lvalue.

And that's allowed, per [algorithms.requirements]. I don't recall exactly why I
did that, I'd have to check the commit logs or mailing list.

I suppose we could do something like:

  if constexpr (is_invocable_v<F&, T&>)
    _M_f(arg);
  else
    _M_f(std::forward<T>(arg));

that would pass an lvalue unless doing so would not compile, and then forward
the original value category. That would use lvalues for correct code (for
whatever reason we had for doing it that way), but would also allow some
invalid cases like this to continue to work, despite violating the
requirements.

Reply via email to