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

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Dmytro Ovdiienko from comment #0)
> It seems the issue is std::uninitialized_copy function. For some reason in
> order to use memcpy it requires the class to be trivially_constructible:
> 
>       if constexpr (!__is_trivially_constructible(_ValT, decltype(*__first)))
>       return std::__do_uninit_copy(__first, __last, __result);
>       else if constexpr (__memcpyable<_Dest, _Src>::__value)
>       {
>         ptrdiff_t __n = __last - __first;
>         if (__n > 0) [[__likely__]]
>           {
>             using _ValT = typename remove_pointer<_Src>::type;
>             __builtin_memcpy(std::__niter_base(__result),
>                              std::__niter_base(__first),
>                              __n * sizeof(_ValT));
>             __result += __n;
>           }
>         return __result;
>       }
> 
> ... while from my perspective it is enough to be trivially destructible and
> trivially copyable/moveable.

I think you're misunderstanding the code. When initializing a range or T from a
range of X we require that constructing T from X is trivial. That is obviously
required, we can't use memcpy to construct this type from a range of int:

struct NegInt { NegInt(int i) : n(-i) { } int n; };

We *also* require that it's trivially copyable, because otherwise using memcpy
has undefined behaviour.

In your case, the range being copied has the same type as the range being
initialized, so the condition is that my_optional<int,-1> can be trivially
constructed from my_optional<int, -1>, which is true.

So that code in std::uninitialized_copy is not the issue.

As noted above, the problem is in the __relocate function, not
uninitialized_copy.

Reply via email to