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);

Reply via email to