https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68350
--- Comment #12 from Arthur O'Dwyer <arthur.j.odwyer at gmail dot com> --- jwakely wrote: > Correction: they need to be the same type. We can't memcpy here: > > struct A { }; > struct B { B() = default; B(A) { do_stuff(); } }; > > void (A* f, A* l, B* out) { > std::uninitialized_copy(f, l, out); > } Right, in your case, the ctor `B(A)` runs user-defined code (it's not "trivial") so obviously we can't do the optimization. But even in general, see my 2018 blog post "Trivially-constructible-from." https://quuxplusone.github.io/blog/2018/07/03/trivially-constructible-from/ using A2 = long long; using B2 = int64_t; // for the sake of argument, this is "long int" void (A* f, A* l, B* out) { std::uninitialized_copy(f, l, out); } The library can't, by itself, determine that memcpy would be safe here. The library needs help from the compiler, e.g. via a new compiler builtin __is_trivially_constructible_from(T, U). (This is *not* the same as the existing `is_trivially_constructible<T,U>` type trait, because blog post.)