[RFC PATCH] libstdc++: WIP on library side of C++26 P2786R13 - Trivial Relocatability

Jakub Jelinek jakub@redhat.com
Mon Jun 16 18:54:20 GMT 2025


Hi!

Also, I wonder what calls need to be fully qualified,
all of trivially_relocate, uninitialized_move, destroy,
move?
And the paper says that for arrays it should
instead do in each loop
relocate(begin(first[i]), end(first[i]), *start_lifetime_as<T>(result + i));
-ish stuff, so that needs to be added as well.

On Mon, Jun 16, 2025 at 08:21:16PM +0200, Jakub Jelinek wrote:
> +  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 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 = uninitialized_move(__first, __last, __result);
> +		  destroy(__first, __last);
> +		  return __result;
> +		}
> +	    }
> +	}
> +
> +      // FIXME: This won't work at constexpr time.  std::less uses
> +      // there just < without the cast which won't work either if
> +      // __result and __first don't point into the same object.
> +      if ((__UINTPTR_TYPE__)__result < (__UINTPTR_TYPE__)__first
> +	  || (__UINTPTR_TYPE__)__last < (__UINTPTR_TYPE__)__result)
> +	{
> +	  for (; __first != __last; ++__first, ++__result)
> +	    {
> +	      ::new(__result) _Tp(move(*__first));
> +	      __first->~_Tp();
> +	    }
> +	  return __result;
> +	}
> +      else
> +	{
> +	  _Tp *__ret = __result + __n;
> +	  for (__result = __ret; __last != __first; )
> +	    {
> +	      --__last;
> +	      --__result;
> +	      ::new(__result) _Tp(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();
> +    }

	Jakub



More information about the Libstdc++ mailing list