return offset data()

in code/include/swoc/MemSpan.h [1590:1713]


  return offset <= _size ? self_type{detail::ptr_add(this->data(), offset), std::min(n, _size - offset)} : self_type{};
}

inline constexpr auto
MemSpan<void>::subspan(size_t offset, size_t n) const -> self_type {
  return offset <= _size ? self_type{detail::ptr_add(this->data(), offset), std::min(n, _size - offset)} : self_type{};
}

template <typename T> constexpr auto MemSpan<T>::restrict(size_t n) -> self_type & {
  _count = std::min(_count, n);
  return *this;
}

template <typename T>
auto
MemSpan<void const>::align() const -> self_type {
  return this->align(alignof(T), sizeof(T));
}

template <typename T>
auto
MemSpan<void>::align() const -> self_type {
  return this->align(alignof(T), sizeof(T));
}

inline auto
MemSpan<void const>::align(size_t alignment) const -> self_type {
  auto p       = uintptr_t(_ptr);
  auto padding = p & (alignment - 1);
  size_t size  = 0;
  if (_size > padding) { // if there's not enough to pad, result is zero size.
    size = _size - padding;
  }
  return {reinterpret_cast<void *>(p + padding), size};
}

inline auto
MemSpan<void>::align(size_t alignment) const -> self_type {
  auto &&[ptr, size] = super_type::align(alignment);
  return {ptr, size};
}

inline auto
MemSpan<void const>::align(size_t alignment, size_t obj_size) const -> self_type {
  auto p       = uintptr_t(_ptr);
  auto padding = p & (alignment - 1);
  size_t size  = 0;
  if (_size > padding) { // if there's not enough to pad, result is zero size.
    size = ((_size - padding) / obj_size) * obj_size;
  }
  return {reinterpret_cast<void *>(p + padding), size};
}

inline auto
MemSpan<void>::align(size_t alignment, size_t obj_size) const -> self_type {
  auto &&[ptr, n] = super_type::align(alignment, obj_size);
  return {ptr, n};
}

template <typename U>
MemSpan<U>
MemSpan<void const>::rebind() const {
  static_assert(std::is_const_v<U>, "Cannot rebind MemSpan<const void> to non-const type.");
  return {static_cast<U *>(_ptr), detail::is_span_compatible<value_type, U>::count(_size)};
}

template <typename U>
MemSpan<U>
MemSpan<void>::rebind() const {
  return {static_cast<U *>(_ptr), detail::is_span_compatible<value_type, U>::count(_size)};
}

// Specialize so that @c void -> @c void rebinding compiles and works as expected.
template <>
inline auto
MemSpan<void const>::rebind() const -> self_type {
  return *this;
}

template <>
inline auto
MemSpan<void>::rebind() const -> self_type {
  return *this;
}

template <>
inline auto
MemSpan<void>::rebind() const -> MemSpan<void const> {
  return {_ptr, _size};
}

template <typename U>
U *
MemSpan<void>::as_ptr() const {
  if (_size != sizeof(U)) {
    throw std::invalid_argument("MemSpan::as size is not compatible with target type.");
  }
  return static_cast<U *>(_ptr);
}

template <typename U>
U const *
MemSpan<void const>::as_ptr() const {
  if (_size != sizeof(U)) {
    throw std::invalid_argument("MemSpan::as size is not compatible with target type.");
  }
  return static_cast<U const *>(_ptr);
}

/// Deduction guides
template <typename T, size_t N> MemSpan(std::array<T, N> &) -> MemSpan<T>;
template <typename T, size_t N> MemSpan(std::array<T, N> const &) -> MemSpan<T const>;
template <size_t N> MemSpan(char (&)[N]) -> MemSpan<char>;
template <size_t N> MemSpan(char const (&)[N]) -> MemSpan<char const>;
template <typename T> MemSpan(std::vector<T> &) -> MemSpan<T>;
template <typename T> MemSpan(std::vector<T> const &) -> MemSpan<T const>;
MemSpan(std::string_view const &) -> MemSpan<char const>;
MemSpan(std::string &) -> MemSpan<char>;
MemSpan(std::string const &) -> MemSpan<char const>;

namespace detail {
struct malloc_liberator {
  void
  operator()(void *ptr) {