On Thu, 27 Jun 2024 at 14:27, Maciej Cencora <m.cenc...@gmail.com> wrote: > > I think going the bit_cast way would be the best because it enables the > optimization for many more classes including common wrappers like optional, > variant, pair, tuple and std::array.
This isn't tested but seems to work on simple cases. But for large objects the loop hits the constexpr iteration limit and compilation fails, so it needs a sizeof(_Tp) < 64 or something. using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; using _Tp = remove_all_extents_t<_ValueType>; // Need value-init to be equivalent to zero-init. if constexpr (is_member_pointer<_Tp>::value) return nullptr; else if constexpr (!is_scalar<_Tp>::value) { using __trivial = __and_<is_trivial<_ValueType>, is_trivially_constructible<_ValueType>>; if constexpr (__trivial::value) { struct _Bytes { unsigned char __b[sizeof(_Tp)]; #if __cpp_constexpr >= 201304 constexpr bool _M_nonzero() const { for (auto __c : __b) if (__c) return true; return false; } #else constexpr bool _M_nonzero(size_t __n = 0) const { return __n < sizeof(_Tp) && (__b[__n] || _M_nonzero(__n + 1)); } #endif }; if constexpr (__builtin_bit_cast(_Bytes, _Tp())._M_nonzero()) return nullptr; } } using _Ptr = decltype(std::__to_address(__first)); // Cannot use memset if _Ptr is cv-qualified. if constexpr (is_convertible<_Ptr, void*>::value) return std::__to_address(__first);