I have tried using array inside unanimous union instead of local char
buffer, but was blocked by following issue:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121068

The idea here, would be to have a function:
template<typename T, size_t N>
void star_array_lifetime(T(&arr)[N])
{
   new(arr) T[N];
   for (int i = 0; i < N; ++i)
     arr[i].~T();
}

And the in test instead of operating on char buffer, use array inside
anonymous union:
    union { S a[20]; };
    star_array_lifetime(a);

After that, the remaining placement new code should work correctly, when
PR121068 is fixed.

On Mon, Jul 14, 2025 at 3:30 PM Tomasz Kaminski <tkami...@redhat.com> wrote:

>
>
> On Tue, Jun 17, 2025 at 1:15 PM Jakub Jelinek <ja...@redhat.com> wrote:
>
>> Hi!
>>
>> Here is a new version of the library side of the C++26 P2786R13 paper.
>> For if constexpr the patch uses __builtin_constant_p trick to figure
>> out if __result is non-equality comparable with __first, it adds recursion
>> for the is_array_v cases, adds qualification on several calls and rewrites
>> the testcase, such that it is hopefully valid and also tests the constant
>> evaluation.
>>
>> 2025-06-17  Jakub Jelinek  <ja...@redhat.com>
>>
>>         PR c++/119064
>>         * include/bits/version.def (trivially_relocatable): New.
>>         * include/bits/version.h: Regenerate.
>>         * include/std/type_traits (std::is_trivially_relocatable,
>>         std::is_nothrow_relocatable, std::is_replaceable): New traits.
>>         std::is_trivially_relocatable_v, std::is_nothrow_relocatable_v,
>>         std::is_replaceable_v): New trait variable templates.
>>         * include/std/memory (__glibcxx_want_trivially_relocatable):
>> Define
>>         before including bits/version.h.
>>         (std::trivially_relocate): New template function.
>>         (std::relocate): Likewise.
>>         * testsuite/std/memory/relocate/relocate.cc: New test.
>>
>> --- libstdc++-v3/include/bits/version.def.jj    2025-06-12
>> 20:19:52.367395730 +0200
>> +++ libstdc++-v3/include/bits/version.def       2025-06-16
>> 22:10:09.415721974 +0200
>> @@ -2012,6 +2012,15 @@ ftms = {
>>    };
>>  };
>>
>> +ftms = {
>> +  name = trivially_relocatable;
>> +  values = {
>> +    v = 202502;
>> +    cxxmin = 26;
>> +    extra_cond = "__cpp_trivial_relocatability >= 202502L";
>> +  };
>> +};
>> +
>>  // Standard test specifications.
>>  stds[97] = ">= 199711L";
>>  stds[03] = ">= 199711L";
>> --- libstdc++-v3/include/bits/version.h.jj      2025-06-12
>> 20:19:52.367395730 +0200
>> +++ libstdc++-v3/include/bits/version.h 2025-06-16 22:10:09.416721960
>> +0200
>> @@ -2253,4 +2253,14 @@
>>  #endif /* !defined(__cpp_lib_sstream_from_string_view) &&
>> defined(__glibcxx_want_sstream_from_string_view) */
>>  #undef __glibcxx_want_sstream_from_string_view
>>
>> +#if !defined(__cpp_lib_trivially_relocatable)
>> +# if (__cplusplus >  202302L) && (__cpp_trivial_relocatability >=
>> 202502L)
>> +#  define __glibcxx_trivially_relocatable 202502L
>> +#  if defined(__glibcxx_want_all) ||
>> defined(__glibcxx_want_trivially_relocatable)
>> +#   define __cpp_lib_trivially_relocatable 202502L
>> +#  endif
>> +# endif
>> +#endif /* !defined(__cpp_lib_trivially_relocatable) &&
>> defined(__glibcxx_want_trivially_relocatable) */
>> +#undef __glibcxx_want_trivially_relocatable
>> +
>>  #undef __glibcxx_want_all
>> --- libstdc++-v3/include/std/type_traits.jj     2025-06-12
>> 00:20:03.898666479 +0200
>> +++ libstdc++-v3/include/std/type_traits        2025-06-16
>> 22:10:09.416721960 +0200
>> @@ -4245,6 +4245,60 @@ template<typename _Ret, typename _Fn, ty
>>
>>  #endif // C++2a
>>
>> +#if __glibcxx_trivially_relocatable >= 202502L // C++ >= 26 &&
>> __cpp_trivial_relocatability >= 202502
>> +  /// True if the type is a trivially relocatable type.
>> +  /// @since C++26
>> +
>> +  template<typename _Tp>
>> +    struct is_trivially_relocatable
>> +# if __has_builtin(__builtin_is_trivially_relocatable)
>> +    : bool_constant<__builtin_is_trivially_relocatable(_Tp)>
>> +# else
>> +    : bool_constant<__builtin_is_cpp_trivially_relocatable(_Tp)>
>> +# endif
>> +    { };
>> +
>> +  template<typename _Tp>
>> +    struct is_nothrow_relocatable
>> +# if _GLIBCXX_USE_BUILTIN_TRAIT(__builtin_is_nothrow_relocatable)
>> +    : bool_constant<__builtin_is_nothrow_relocatable(_Tp)>
>> +# else
>> +    : public __or_<is_trivially_relocatable<_Tp>,
>> +
>> __and_<is_nothrow_move_constructible<remove_all_extents<_Tp>>,
>> +
>>  is_nothrow_destructible<remove_all_extends<_Tp>>>>::type
>> +# endif
>> +    { };
>> +
>> +  template<typename _Tp>
>> +    struct is_replaceable
>> +    : bool_constant<__builtin_is_replaceable(_Tp)>
>> +    { };
>> +
>> +  /// @ingroup variable_templates
>> +  /// @since C++26
>> +  template<typename _Tp>
>> +    inline constexpr bool is_trivially_relocatable_v
>> +# if __has_builtin(__builtin_is_trivially_relocatable)
>> +      = __builtin_is_trivially_relocatable(_Tp);
>> +# else
>> +      = __builtin_is_cpp_trivially_relocatable(_Tp);
>> +# endif
>> +
>> +  template<typename _Tp>
>> +    inline constexpr bool is_nothrow_relocatable_v
>> +# if _GLIBCXX_USE_BUILTIN_TRAIT(__builtin_is_nothrow_relocatable)
>> +      = __builtin_is_nothrow_relocatable(_Tp);
>> +# else
>> +      = (is_trivially_relocatable_v<_Tp>
>> +        || (is_nothrow_move_constructible_v<remove_all_extents<_Tp>>
>> +            && is_nothrow_destructible_v<remove_all_extents<_Tp>>);
>> +# endif
>> +
>> +  template<typename _Tp>
>> +    inline constexpr bool is_replaceable_v
>> +      = __builtin_is_replaceable(_Tp);
>> +#endif
>> +
>>    /// @} group metaprogramming
>>
>>  _GLIBCXX_END_NAMESPACE_VERSION
>> --- libstdc++-v3/include/std/memory.jj  2025-06-02 21:58:22.148775743
>> +0200
>> +++ libstdc++-v3/include/std/memory     2025-06-17 12:03:01.249069663
>> +0200
>> @@ -121,6 +121,7 @@
>>  #define __glibcxx_want_smart_ptr_for_overwrite
>>  #define __glibcxx_want_to_address
>>  #define __glibcxx_want_transparent_operators
>> +#define __glibcxx_want_trivially_relocatable
>>  #include <bits/version.h>
>>
>>  #if __cplusplus >= 201103L && __cplusplus <= 202002L && _GLIBCXX_HOSTED
>> @@ -170,6 +171,121 @@ _GLIBCXX_END_NAMESPACE_VERSION
>>  } // namespace
>>  #endif // C++11 to C++20
>>
>> +#ifdef __cpp_lib_trivially_relocatable
>> +namespace std _GLIBCXX_VISIBILITY(default)
>> +{
>> +_GLIBCXX_BEGIN_NAMESPACE_VERSION
>> +
>> +  template<typename _Tp>
>> +    [[__gnu__::__always_inline__]]
>> +    inline _Tp*
>> +    trivially_relocate(_Tp* __first, _Tp* __last, _Tp* __result) noexcept
>> +    {
>> +      static_assert(is_trivially_relocatable_v<_Tp> && !is_const_v<_Tp>);
>> +      if (__first == __result)
>> +       return __last;
>> +#if __has_builtin(__builtin_trivially_relocate)
>> +      __builtin_trivially_relocate(__result, __first, __last - __first);
>> +#else
>> +      __builtin_memmove(static_cast<void*>(__result),
>> +                       static_cast<const void*>(__first),
>> +                       (__last - __first) * sizeof(_Tp));
>> +#endif
>> +      return __result + (__last - __first);
>> +    }
>> +
>> +  template<typename _Tp>
>> +    constexpr _Tp*
>> +    relocate(_Tp* __first, _Tp* __last, _Tp* __result) noexcept
>> +    {
>> +      static_assert(is_nothrow_relocatable_v<_Tp> && !is_const_v<_Tp>);
>> +      if !consteval
>> +       {
>> +         if constexpr (is_trivially_relocatable_v<_Tp>)
>> +           return std::trivially_relocate(__first, __last, __result);
>> +       }
>> +      if (__first == __result)
>> +       return __last;
>> +      if (__first == __last)
>> +       return __result;
>> +
>> +      size_t __n = __last - __first;
>> +      if constexpr (is_move_constructible_v<_Tp>)
>> +       {
>> +         if !consteval
>> +           {
>> +             // If there is no overlap, move everything first and then
>> +             // destruct.
>> +             if ((__UINTPTR_TYPE__)__last <= (__UINTPTR_TYPE__)__result
>> +                 || ((__UINTPTR_TYPE__)(__result + __n)
>> +                     <= (__UINTPTR_TYPE__)__first))
>> +               {
>> +                 __result = std::uninitialized_move(__first, __last,
>> +                                                    __result);
>> +                 std::destroy(__first, __last);
>> +                 return __result;
>> +               }
>> +           }
>> +       }
>> +
>> +      bool __fwd = true;
>> +      if consteval
>> +       {
>> +         // Use __builtin_constant_p to determine if __result and __first
>> +         // point into the same object, if they don't, there is no
>> overlap
>> +         // and so either __fwd or !__fwd is fine.
>> +         if (__builtin_constant_p (__result < __first)
>> +             && __result > __first
>> +             && __result < __last)
>> +           __fwd = false;
>> +       }
>> +      else
>> +       {
>> +         __fwd = ((__UINTPTR_TYPE__)__result - (__UINTPTR_TYPE__)__first
>> +                  >= (__UINTPTR_TYPE__)__last -
>> (__UINTPTR_TYPE__)__first);
>> +       }
>> +      if (__builtin_expect(__fwd, true))
>> +       {
>> +         for (; __first != __last; ++__first, ++__result)
>> +           {
>> +             if constexpr (is_array_v<_Tp>)
>> +               std::relocate(std::begin(*__first), std::end(*__first),
>> +                             &(*__result)[0]);
>> +             else
>> +               {
>> +                 ::new(__result) _Tp(std::move(*__first));
>> +                 __first->~_Tp();
>> +               }
>> +           }
>> +         return __result;
>> +       }
>> +      else
>> +       {
>> +         _Tp *__ret = __result + __n;
>> +         for (__result = __ret; __last != __first; )
>> +           {
>> +             --__last;
>> +             --__result;
>> +             if constexpr (is_array_v<_Tp>)
>> +               std::relocate(std::begin(*__last), std::end(*__last),
>> +                             &(*__result)[0]);
>> +             else
>> +               {
>> +                 ::new(__result) _Tp(std::move(*__last));
>> +                 __last->~_Tp();
>> +               }
>> +           }
>> +         return __ret;
>> +       }
>> +      // If at constand evaluation is_trivially_relocatable_v<_Tp>
>> +      // but not is_move_constructible_V<_Tp>, fail.
>> +      __builtin_unreachable();
>> +    }
>> +
>> +_GLIBCXX_END_NAMESPACE_VERSION
>> +} // namespace
>> +#endif
>> +
>>  #ifdef __cpp_lib_parallel_algorithm // C++ >= 17 && HOSTED
>>  // Parallel STL algorithms
>>  # if _PSTL_EXECUTION_POLICIES_DEFINED
>> --- libstdc++-v3/testsuite/std/memory/relocate/relocate.cc.jj
>>  2025-06-16 22:10:09.417721947 +0200
>> +++ libstdc++-v3/testsuite/std/memory/relocate/relocate.cc
>> 2025-06-17 13:03:48.309023611 +0200
>> @@ -0,0 +1,305 @@
>> +// { dg-do run { target c++26 } }
>> +
>> +#include <memory>
>> +
>> +#include <testsuite_hooks.h>
>> +#include <testsuite_allocator.h>
>> +
>> +struct S trivially_relocatable_if_eligible
>> +{
>> +  S() : s(0) {}
>> +  S(int x) : s(x) {}
>> +  S(S&& x) : s(x.s) {}
>> +  S& operator=(S&& x) { s = x.s; return *this; }
>> +  unsigned char s;
>> +};
>> +
>> +struct T
>> +{
>> +  T() : t(0) {}
>> +  T(int x) : t(x) {}
>> +  T(T&& x) noexcept : t(x.t) {}
>> +  T& operator=(T&& x) { t = x.t; return *this; }
>> +  unsigned char t;
>> +};
>> +
>> +static_assert(std::is_trivially_relocatable_v<S>);
>> +static_assert(std::is_nothrow_relocatable_v<S>);
>> +static_assert(std::is_nothrow_relocatable_v<T>);
>> +
>> +constexpr void
>> +test_relocate()
>> +{
>> +  unsigned char a[20], b[20], c[20], d[20];
>> +  S *sf, *sl, *sr;
>> +  T *tf, *tl, *tr;
>> +  sf = ::new(&a[2]) S(11);
>> +  tf = ::new(&b[2]) T(11);
>> +  for (int i = 3; i < 8; ++i)
>> +    {
>> +      sl = ::new(&a[i]) S(i + 9);
>> +      tl = ::new(&b[i]) T(i + 9);
>> +    }
>> +  ++sl;
>> +  ++tl;
>> +  sr = ::new(&c[5]) S(42);
>> +  tr = ::new(&d[5]) T(42);
>> +  sr->~S();
>> +  tr->~T();
>> +  VERIFY( std::relocate(sf, sl, sr) == sr + 6 );
>> +  VERIFY( std::relocate(tf, tl, tr) == tr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( sr->s == i + 11 );
>> +      VERIFY( tr->t == i + 11 );
>> +      sr->~S();
>> +      tr->~T();
>> +      ++sr;
>> +      ++tr;
>> +    }
>> +  sf = ::new(&a[2]) S(11);
>> +  tf = ::new(&b[2]) T(11);
>> +  for (int i = 3; i < 8; ++i)
>> +    {
>> +      sl = ::new(&a[i]) S(i + 9);
>> +      tl = ::new(&b[i]) T(i + 9);
>> +    }
>> +  ++sl;
>> +  ++tl;
>> +  sr = ::new(&a[1]) S(42);
>> +  tr = ::new(&a[1]) T(42);
>> +  sr->~S();
>> +  tr->~T();
>> +  VERIFY( std::relocate(sf, sl, sr) == sr + 6 );
>> +  VERIFY( std::relocate(tf, tl, tr) == tr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( sr->s == i + 11 );
>> +      VERIFY( tr->t == i + 11 );
>> +      sr->~S();
>> +      tr->~T();
>> +      ++sr;
>> +      ++tr;
>> +    }
>> +  sf = ::new(&a[2]) S(11);
>> +  tf = ::new(&b[2]) T(11);
>> +  for (int i = 3; i < 8; ++i)
>> +    {
>> +      sl = ::new(&a[i]) S(i + 9);
>> +      tl = ::new(&b[i]) T(i + 9);
>> +    }
>> +  ++sl;
>> +  ++tl;
>> +  sr = sf + 1;
>> +  tr = tf + 1;
>> +  VERIFY( std::relocate(sf, sl, sr) == sr + 6 );
>> +  VERIFY( std::relocate(tf, tl, tr) == tr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( sr->s == i + 11 );
>> +      VERIFY( tr->t == i + 11 );
>> +      sr->~S();
>> +      tr->~T();
>> +      ++sr;
>> +      ++tr;
>> +    }
>> +}
>> +
>> +constexpr void
>> +test_relocate_array()
>> +{
>> +  unsigned char a[20], b[20], c[20], d[20];
>> +  using SA = S[2];
>> +  using TA = T[2];
>> +  SA *sf, *sl, *sr;
>> +  TA *tf, *tl, *tr;
>> +  sf = (SA *)(::new(&a[2]) SA{11, 12});
>> +  tf = (TA *)(::new(&b[2]) TA{11, 12});
>> +  for (int i = 0; i < 5; ++i)
>> +    {
>> +      sl = (SA *)(::new(&a[4 + 2 * i]) SA{13 + 2 * i, 14 + 2 * i});
>> +      tl = (TA *)(::new(&b[4 + 2 * i]) TA{13 + 2 * i, 14 + 2 * i});
>> +    }
>> +  ++sl;
>> +  ++tl;
>> +  sr = (SA *)(::new(&c[6]) SA{42, 42});
>> +  tr = (TA *)(::new(&d[6]) TA{42, 42});
>> +  (*sr)[0].~S();
>> +  (*sr)[1].~S();
>> +  (*tr)[0].~T();
>> +  (*tr)[1].~T();
>> +  VERIFY( std::relocate(sf, sl, sr) == sr + 6 );
>> +  VERIFY( std::relocate(tf, tl, tr) == tr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( (*sr)[0].s == 2 * i + 11 && (*sr)[1].s == 2 * i + 12 );
>> +      VERIFY( (*tr)[0].t == 2 * i + 11 && (*tr)[1].t == 2 * i + 12 );
>> +      (*sr)[0].~S();
>> +      (*sr)[1].~S();
>> +      (*tr)[0].~T();
>> +      (*tr)[1].~T();
>> +      ++sr;
>> +      ++tr;
>> +    }
>> +  sf = (SA *)(::new(&a[2]) SA{11, 12});
>> +  tf = (TA *)(::new(&b[2]) TA{11, 12});
>> +  for (int i = 0; i < 5; ++i)
>> +    {
>> +      sl = (SA *)(::new(&a[4 + 2 * i]) SA{13 + 2 * i, 14 + 2 * i});
>> +      tl = (TA *)(::new(&b[4 + 2 * i]) TA{13 + 2 * i, 14 + 2 * i});
>> +    }
>> +  ++sl;
>> +  ++tl;
>> +  sr = (SA *)(::new(&a[0]) SA{42, 42});
>> +  tr = (TA *)(::new(&b[0]) TA{42, 42});
>> +  (*sr)[0].~S();
>> +  (*sr)[1].~S();
>> +  (*tr)[0].~T();
>> +  (*tr)[1].~T();
>> +  VERIFY( std::relocate(sf, sl, sr) == sr + 6 );
>> +  VERIFY( std::relocate(tf, tl, tr) == tr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( (*sr)[0].s == 2 * i + 11 && (*sr)[1].s == 2 * i + 12 );
>> +      VERIFY( (*tr)[0].t == 2 * i + 11 && (*tr)[1].t == 2 * i + 12 );
>> +      (*sr)[0].~S();
>> +      (*sr)[1].~S();
>> +      (*tr)[0].~T();
>> +      (*tr)[1].~T();
>> +      ++sr;
>> +      ++tr;
>> +    }
>> +  sf = (SA *)(::new(&a[2]) SA{11, 12});
>> +  tf = (TA *)(::new(&b[2]) TA{11, 12});
>> +  for (int i = 0; i < 5; ++i)
>> +    {
>> +      sl = (SA *)(::new(&a[4 + 2 * i]) SA{13 + 2 * i, 14 + 2 * i});
>> +      tl = (TA *)(::new(&b[4 + 2 * i]) TA{13 + 2 * i, 14 + 2 * i});
>> +    }
>> +  ++sl;
>> +  ++tl;
>> +  sr = sf + 1;
>> +  tr = tf + 1;
>> +  VERIFY( std::relocate(sf, sl, sr) == sr + 6 );
>> +  VERIFY( std::relocate(tf, tl, tr) == tr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( (*sr)[0].s == 2 * i + 11 && (*sr)[1].s == 2 * i + 12 );
>> +      VERIFY( (*tr)[0].t == 2 * i + 11 && (*tr)[1].t == 2 * i + 12 );
>> +      (*sr)[0].~S();
>> +      (*sr)[1].~S();
>> +      (*tr)[0].~T();
>> +      (*tr)[1].~T();
>> +      ++sr;
>> +      ++tr;
>> +    }
>> +}
>> +
>> +void
>> +test_trivially_relocate()
>> +{
>> +  unsigned char a[20], c[20];
>> +  S *sf, *sl, *sr;
>> +  sf = ::new(&a[2]) S(11);
>> +  for (int i = 3; i < 8; ++i)
>> +    sl = ::new(&a[i]) S(i + 9);
>> +  ++sl;
>> +  sr = ::new(&c[5]) S(42);
>> +  sr->~S();
>> +  VERIFY( std::trivially_relocate(sf, sl, sr) == sr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( sr->s == i + 11 );
>> +      sr->~S();
>> +      ++sr;
>> +    }
>> +  sf = ::new(&a[2]) S(11);
>> +  for (int i = 3; i < 8; ++i)
>> +    sl = ::new(&a[i]) S(i + 9);
>> +  ++sl;
>> +  sr = ::new(&a[1]) S(42);
>> +  sr->~S();
>> +  VERIFY( std::trivially_relocate(sf, sl, sr) == sr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( sr->s == i + 11 );
>> +      sr->~S();
>> +      ++sr;
>> +    }
>> +  sf = ::new(&a[2]) S(11);
>> +  for (int i = 3; i < 8; ++i)
>> +    sl = ::new(&a[i]) S(i + 9);
>> +  ++sl;
>> +  sr = sf + 1;
>> +  VERIFY( std::trivially_relocate(sf, sl, sr) == sr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( sr->s == i + 11 );
>> +      sr->~S();
>> +      ++sr;
>> +    }
>> +}
>> +
>> +void
>> +test_trivially_relocate_array()
>> +{
>> +  unsigned char a[20], c[20];
>> +  using SA = S[2];
>> +  SA *sf, *sl, *sr;
>> +  sf = (SA *)(::new(&a[2]) SA{11, 12});
>> +  for (int i = 0; i < 5; ++i)
>> +    sl = (SA *)(::new(&a[4 + 2 * i]) SA{13 + 2 * i, 14 + 2 * i});
>> +  ++sl;
>> +  sr = (SA *)(::new(&c[6]) SA{42, 42});
>> +  (*sr)[0].~S();
>> +  (*sr)[1].~S();
>> +  VERIFY( std::trivially_relocate(sf, sl, sr) == sr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( (*sr)[0].s == 2 * i + 11 && (*sr)[1].s == 2 * i + 12 );
>> +      (*sr)[0].~S();
>> +      (*sr)[1].~S();
>> +      ++sr;
>> +    }
>> +  sf = (SA *)(::new(&a[2]) SA{11, 12});
>> +  for (int i = 0; i < 5; ++i)
>> +    sl = (SA *)(::new(&a[4 + 2 * i]) SA{13 + 2 * i, 14 + 2 * i});
>> +  ++sl;
>> +  sr = (SA *)(::new(&a[0]) SA{42, 42});
>> +  (*sr)[0].~S();
>> +  (*sr)[1].~S();
>> +  VERIFY( std::trivially_relocate(sf, sl, sr) == sr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( (*sr)[0].s == 2 * i + 11 && (*sr)[1].s == 2 * i + 12 );
>> +      (*sr)[0].~S();
>> +      (*sr)[1].~S();
>> +      ++sr;
>> +    }
>> +  sf = (SA *)(::new(&a[2]) SA{11, 12});
>> +  for (int i = 0; i < 5; ++i)
>> +    sl = (SA *)(::new(&a[4 + 2 * i]) SA{13 + 2 * i, 14 + 2 * i});
>> +  ++sl;
>> +  sr = sf + 1;
>> +  VERIFY( std::trivially_relocate(sf, sl, sr) == sr + 6 );
>> +  for (int i = 0; i < 6; ++i)
>> +    {
>> +      VERIFY( (*sr)[0].s == 2 * i + 11 && (*sr)[1].s == 2 * i + 12 );
>> +      (*sr)[0].~S();
>> +      (*sr)[1].~S();
>> +      ++sr;
>> +    }
>> +}
>> +
>> +int main()
>> +{
>> +  test_relocate();
>> +  test_trivially_relocate();
>> +  test_relocate_array();
>> +  test_trivially_relocate_array();
>> +  static_assert([] {
>> +    test_relocate();
>> +    test_relocate_array();
>> +    return true;
>> +  });
>
> The lambda is not invoked here, i.e. we should have "}())", and we are now
> testing
> if the conversion to funciton pointer produces a non-null pointer, which
> is true. After fixing
> the line, I get a lot of errors about missing constexpr on S and T
> constructors.
> After that, the placement of new calls are failing and reinterpret_cast.
>
> I am not yet sure how to write a constexpr compatible test for this
> functionality.
>
>>
>
> +}
>>
>>         Jakub
>>
>>

Reply via email to