[Bug libstdc++/93872] [10 Regression] std::move(first, last, out) with a move-only value type fails to compile with -std=c++2a

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Tue Feb 25 11:47:00 GMT 2020


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

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
It looks like those parameters have always been wrong (for more than a decade
anyway). When we optimized them to a memmove for both copies and moves it
didn't matter because memmove doesn't alter the source and so it can be const.

For C++20 when std::is_constant_evaluated() is true, we do the actual
assignments in a loop, and so the value category and cv-qualifiers need to be
correct.

I'm nervous about changing the parameter types in stage 4 because it affects
all modes, not just C++20. I think the conservative fix for now is:

--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -95,7 +95,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          for(; __num > 0; --__num)
            {
              if constexpr (_IsMove)
-               *__dst = std::move(*__src);
+               // This const_cast looks unsafe, but we only use this function
+               // for trivially-copyable types, which means this assignment
+               // is trivial and so doesn't alter the source anyway.
+               // See PR 93872 for why it's needed.
+               *__dst = std::move(*const_cast<_Tp*>(__src));
              else
                *__dst = *__src;
              ++__src;


More information about the Gcc-bugs mailing list