4

I see this code in libstdc++ stl_uninitialized.h:

  // This class may be specialized for specific types.
  // Also known as is_trivially_relocatable.
  template<typename _Tp, typename = void>
    struct __is_bitwise_relocatable
    : is_trivial<_Tp> { };

  template <typename _Tp, typename _Up>
    inline __enable_if_t<std::__is_bitwise_relocatable<_Tp>::value, _Tp*>
    __relocate_a_1(_Tp* __first, _Tp* __last,
           _Tp* __result, allocator<_Up>&) noexcept
    {
      ptrdiff_t __count = __last - __first;
      if (__count > 0)
    __builtin_memmove(__result, __first, __count * sizeof(_Tp));
      return __result + __count;
    }

But it seems to me that memmove would be fine for objects that are trivially copyable even if they are not trivially default constructable. Who cares about the default constructor in this case?

Dan Stahlke
  • 1,417
  • 1
  • 15
  • 20
  • 2
    Relevant discussion: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87106 – Anton Jan 11 '20 at 00:13
  • It appears this bugzilla thread was the genesis of this __is_bitwise_relocatable trait (I didn't follow much of the discussion). My question then becomes: is there any reason why is_trivially_copyable isn't on its own enough to enable __is_bitwise_relocatable and trigger the memcpy? – Dan Stahlke Jan 16 '20 at 02:06
  • For those interested: folly::FBVector allows you to manually mark a class as being relocatable so you can gain the performance benefit of memcpy. – Dan Stahlke Jan 16 '20 at 02:07
  • Speaking of FBVector: My WG21 proposal [P1144 "Object relocation in terms of move plus destroy"](https://wg21.link/p1144r4) (targeting C++2b or later) is implemented in my fork of Clang, on Compiler Explorer [here](https://p1144.godbolt.org/z/RoWQdD). libstdc++, libc++, and MSVC all are happy to pop `trivial` types into existence without a constructor call (e.g. via `memcpy` or `memmove`), and are all loath to pop `trivially_copyable` types into existence the same way. This applies to `vector::reserve` just as much as to `uninitialized_copy`. – Quuxplusone Jan 16 '20 at 19:24

1 Answers1

4

I asked about it on the bugzilla thread and they pointed me to https://stackoverflow.com/questions/47464819. Essentially, memcpy isn't enough to start the lifetime of the object, unless the default constructor is also trivial. So it could technically be okay in terms of the bits in memory, but would be undefined behavior according to the standard. Since this library code is written by the compiler team they have the right to do it anyway if they thought it was safe, but they are apparently not convinced of the safety.

Dan Stahlke
  • 1,417
  • 1
  • 15
  • 20
  • 1
    A good way of saying this is that (at the level of the standard) trivial copyability applies between **objects**, not between an object and memory. – Davis Herring Jan 18 '20 at 17:16
  • _"Since this library code is written by the compiler team they have the right to do it anyway if they thought it was safe"_ ... yes, in theory, but I know for a fact it **isn't** safe with GCC. We're only allowed to break semantic rules like that if the result is still correct, but in this case it would trigger undefined behaviour whether it's in the library header or not. – Jonathan Wakely Jan 21 '20 at 12:10