https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108846
--- Comment #22 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Jonathan Wakely from comment #16) > const ptrdiff_t _Num = __last - __first; > - if (_Num) > + if (__builtin_expect(_Num > 1, true)) > __builtin_memmove(__result, __first, sizeof(_Tp) * _Num); > + else if (_Num == 1) Richi suggested that we could avoid these runtime branches (which hurt optimization, see PR 109445) if we knew how many bytes of tail padding there are in _Tp, e.g., __builtin_memmove(__result, __first, sizeof(_Tp) * _Num - __padding_bytes); This would mean we copy whole objects for the first Num - 1 elements, and then only copy the non-padding bytes for the last element. This would be conforming, because there's no guarantee that padding bits are copied by assignment anyway, and std::copy is specified in terms of assignment. When copying a single base-class object (the subject of this bug) the last element is the only element, so we solve the problem. We don't have a built-in to tell us the number of padding bytes, but we might be able to use something like this: template<typename T> constexpr size_t potentially_overlapping_tail_padding() { if constexpr (is_final<T>::value) return 0; else { struct D1 : T { char c1; }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Winvalid-offsetof" return sizeof(T) - offsetof(D1, c1); #pragma GCC diagnostic pop } } For pre-C++17 we would need to use tag dispatching and __is_final instead of if-constexpr, but that's doable. For pre-C++14 it can't be constexpr, but that's OK too.