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

            Bug ID: 116471
           Summary: Strange/bogus static_assert in ranges::copy / move
                    algorithms
           Product: gcc
           Version: 14.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dangelog at gmail dot com
  Target Milestone: ---

Hi,

This code fails to build on GCC 14 (CE link:
https://gcc.godbolt.org/z/qnYGd48Ko )


#include <algorithm>

struct X {
    X& operator=(X&) = default; // non-const
};

int main() {
    extern X *b, *e, *out;
    std::ranges::copy(b, e, out);
}



/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/ranges_algobase.h:259:23:
error: static assertion failed
  258 |                   static_assert(_IsMove
      |                                 ~~~~~~~
  259 |                       ? is_move_assignable_v<_ValueTypeI>
      |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  260 |                       : is_copy_assignable_v<_ValueTypeI>);
      |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/ranges_algobase.h:259:23:
note: '(false ?  std::is_move_assignable_v<X> : std::is_copy_assignable_v<X>)'
evaluates to false



Indeed X fails is_copy_assignable because its copy assignment operator takes by
non-const reference.

It's not entirely clear why that static_assert is there, given that
ranges::copy/move algorithms are already constrained on concepts (like
indirectly_copyable). 

It's also worth noting that the static_assert is into a if constexpr(
__memcpyable<_Iter, _Out>::__value) branch. memcpyable basically means
trivially copyable (except for pointers to volatile), however trivially
copyable does NOT imply is_copy_assignable (because it just checks that
eligible copy assignments are trivial, not that they work from a `const T`).

I can send a patch, but I'm not sure in which direction this should go. I
stumbled upon this while extending the fix PR108846 to range algorithms.

Reply via email to