[Bug libstdc++/89164] can construct vector with non-copyable-but-trivially-copyable elements

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Tue Feb 5 13:12:00 GMT 2019


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

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
This version compiles even in C++11 though:

#include <vector>

struct X {
  X() = default;
  X(const X&) = delete;
};

int main()
{
  X x[1];
  std::vector<X> v{x, x+1};
}

The original version was only rejected prior to C++17 because the
std::initializer_list<X> required a copy constructor, which is elided in C++17.

I think the right fix is:

--- a/libstdc++-v3/include/bits/stl_uninitialized.h
+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
@@ -122,9 +122,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cplusplus < 201103L
       const bool __assignable = true;
 #else
-      // trivial types can have deleted assignment
+      // Trivial types can have deleted copy constructor, but std::copy
+      // optimization that uses memmove would happily "copy" them anyway.
+      static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
+         "result type must be constructible from value type of input range");
+
       typedef typename iterator_traits<_InputIterator>::reference _RefType1;
       typedef typename iterator_traits<_ForwardIterator>::reference _RefType2;
+      // Trivial types can have deleted assignment, so using std::copy
+      // would be ill-formed. Require assignability before using std::copy:
       const bool __assignable = is_assignable<_RefType2, _RefType1>::value;
 #endif


More information about the Gcc-bugs mailing list