Skip to content

Commit

Permalink
[span] Make span standard_layout
Browse files Browse the repository at this point in the history
  • Loading branch information
miscco committed Jun 3, 2020
1 parent 7447ad5 commit 51f0d5b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 41 deletions.
89 changes: 48 additions & 41 deletions stl/inc/span
Original file line number Diff line number Diff line change
Expand Up @@ -226,29 +226,38 @@ struct pointer_traits<_Span_iterator<_Ty>> {
};

// STRUCT TEMPLATE _Span_extent_type
template <size_t _Extent>
template <class _Ty, size_t _Extent>
struct _Span_extent_type {
using pointer = _Ty*;

constexpr _Span_extent_type() noexcept = default;

constexpr explicit _Span_extent_type(size_t) noexcept {}
constexpr explicit _Span_extent_type(const size_t, const pointer _Data) noexcept : _Mydata{_Data} {}

_NODISCARD constexpr size_t size() const noexcept {
return _Extent;
}

protected:
pointer _Mydata{nullptr};
};

template <>
struct _Span_extent_type<dynamic_extent> {
template <class _Ty>
struct _Span_extent_type<_Ty, dynamic_extent> {
using pointer = _Ty*;

constexpr _Span_extent_type() noexcept = default;

constexpr explicit _Span_extent_type(const size_t _Size) noexcept : _Mysize(_Size) {}
constexpr explicit _Span_extent_type(const size_t _Size, const pointer _Data) noexcept
: _Mysize(_Size), _Mydata{_Data} {}

_NODISCARD constexpr size_t size() const noexcept {
return _Mysize;
}

private:
protected:
size_t _Mysize{0};
pointer _Mydata{nullptr};
};

template <class _Ty, size_t _Size>
Expand Down Expand Up @@ -346,7 +355,7 @@ inline constexpr bool _Is_span_compatible_range = conjunction_v<
// [views.span]
// CLASS TEMPLATE span
template <class _Ty, size_t _Extent = dynamic_extent>
class span : public _Span_extent_type<_Extent> {
class span : public _Span_extent_type<_Ty, _Extent> {
public:
using element_type = _Ty;
using value_type = remove_cv_t<_Ty>;
Expand All @@ -369,7 +378,7 @@ public:

template <_Span_compatible_iterator<element_type> _It>
constexpr explicit(_Extent != dynamic_extent) span(_It _First, size_type _Count) noexcept // strengthened
: _Mybase(_Count), _Mydata(_STD to_address(_Get_unwrapped_n(_First, _Count))) {
: _Mybase(_Count, _STD to_address(_Get_unwrapped_n(_First, _Count))) {
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
_STL_VERIFY(_Count == _Extent,
Expand All @@ -381,7 +390,7 @@ public:
template <_Span_compatible_iterator<element_type> _It, _Span_compatible_sentinel<_It> _Sentinel>
constexpr explicit(_Extent != dynamic_extent) span(_It _First, _Sentinel _Last)
noexcept(noexcept(_Last - _First)) // strengthened
: _Mybase(static_cast<size_type>(_Last - _First)), _Mydata(_STD to_address(_First)) {
: _Mybase(static_cast<size_type>(_Last - _First),_STD to_address(_First)) {
_Adl_verify_range(_First, _Last);
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
Expand All @@ -393,21 +402,21 @@ public:

template <size_t _Size>
requires (_Extent == dynamic_extent || _Extent == _Size)
constexpr span(type_identity_t<element_type> (&_Arr)[_Size]) noexcept : _Mybase(_Size), _Mydata(_Arr) {}
constexpr span(type_identity_t<element_type> (&_Arr)[_Size]) noexcept : _Mybase(_Size, _Arr) {}

template <class _OtherTy, size_t _Size>
requires (_Extent == dynamic_extent || _Extent == _Size)
&& is_convertible_v<_OtherTy (*)[], element_type (*)[]>
constexpr span(array<_OtherTy, _Size>& _Arr) noexcept : _Mybase(_Size), _Mydata(_Arr.data()) {}
constexpr span(array<_OtherTy, _Size>& _Arr) noexcept : _Mybase(_Size, _Arr.data()) {}

template <class _OtherTy, size_t _Size>
requires (_Extent == dynamic_extent || _Extent == _Size)
&& is_convertible_v<const _OtherTy (*)[], element_type (*)[]>
constexpr span(const array<_OtherTy, _Size>& _Arr) noexcept : _Mybase(_Size), _Mydata(_Arr.data()) {}
constexpr span(const array<_OtherTy, _Size>& _Arr) noexcept : _Mybase(_Size, _Arr.data()) {}

template <_Span_compatible_range<element_type> _Rng>
constexpr explicit(_Extent != dynamic_extent) span(_Rng&& _Range)
: _Mybase(static_cast<size_type>(_RANGES size(_Range))), _Mydata(_RANGES data(_Range)) {
: _Mybase(static_cast<size_type>(_RANGES size(_Range)), _RANGES data(_Range)) {
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
_STL_VERIFY(_RANGES size(_Range) == _Extent,
Expand All @@ -421,7 +430,7 @@ public:
&& is_convertible_v<_OtherTy (*)[], element_type (*)[]>
constexpr explicit(_Extent != dynamic_extent && _OtherExtent == dynamic_extent)
span(const span<_OtherTy, _OtherExtent>& _Other) noexcept
: _Mybase(_Other.size()), _Mydata(_Other.data()) {
: _Mybase(_Other.size(), _Other.data()) {
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
_STL_VERIFY(_Other.size() == _Extent,
Expand All @@ -437,7 +446,7 @@ public:
constexpr span() noexcept {}

constexpr explicit(_Extent != dynamic_extent) span(pointer _Ptr, size_type _Count) noexcept // strengthened
: _Mybase(_Count), _Mydata(_Ptr) {
: _Mybase(_Count, _Ptr) {
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
_STL_VERIFY(_Count == _Extent,
Expand All @@ -447,7 +456,7 @@ public:
}

constexpr explicit(_Extent != dynamic_extent) span(pointer _First, pointer _Last) noexcept // strengthened
: _Mybase(static_cast<size_type>(_Last - _First)), _Mydata(_First) {
: _Mybase(static_cast<size_type>(_Last - _First), _First) {
_Adl_verify_range(_First, _Last);
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
Expand All @@ -458,23 +467,23 @@ public:
}

template <size_t _Size, enable_if_t<_Extent == dynamic_extent || _Extent == _Size, int> = 0>
constexpr span(element_type (&_Arr)[_Size]) noexcept : _Mybase(_Size), _Mydata(_Arr) {}
constexpr span(element_type (&_Arr)[_Size]) noexcept : _Mybase(_Size, _Arr) {}

template <class _OtherTy, size_t _Size,
enable_if_t<conjunction_v<bool_constant<_Extent == dynamic_extent || _Extent == _Size>,
is_convertible<_OtherTy (*)[], element_type (*)[]>>,
int> = 0>
constexpr span(array<_OtherTy, _Size>& _Arr) noexcept : _Mybase(_Size), _Mydata(_Arr.data()) {}
constexpr span(array<_OtherTy, _Size>& _Arr) noexcept : _Mybase(_Size, _Arr.data()) {}

template <class _OtherTy, size_t _Size,
enable_if_t<conjunction_v<bool_constant<_Extent == dynamic_extent || _Extent == _Size>,
is_convertible<const _OtherTy (*)[], element_type (*)[]>>,
int> = 0>
constexpr span(const array<_OtherTy, _Size>& _Arr) noexcept : _Mybase(_Size), _Mydata(_Arr.data()) {}
constexpr span(const array<_OtherTy, _Size>& _Arr) noexcept : _Mybase(_Size, _Arr.data()) {}

template <class _Rng, enable_if_t<_Is_span_compatible_range<_Rng, element_type>, int> = 0>
constexpr explicit(_Extent != dynamic_extent) span(_Rng& _Range)
: _Mybase(static_cast<size_type>(_STD size(_Range))), _Mydata(_STD data(_Range)) {
: _Mybase(static_cast<size_type>(_STD size(_Range)), _STD data(_Range)) {
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
_STL_VERIFY(_STD size(_Range) == _Extent,
Expand All @@ -485,7 +494,7 @@ public:

template <class _Rng, enable_if_t<_Is_span_compatible_range<const _Rng, element_type>, int> = 0>
constexpr explicit(_Extent != dynamic_extent) span(const _Rng& _Range)
: _Mybase(static_cast<size_type>(_STD size(_Range))), _Mydata(_STD data(_Range)) {
: _Mybase(static_cast<size_type>(_STD size(_Range)), _STD data(_Range)) {
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
_STL_VERIFY(_STD size(_Range) == _Extent,
Expand All @@ -501,7 +510,7 @@ public:
int> = 0>
constexpr explicit(_Extent != dynamic_extent && _OtherExtent == dynamic_extent)
span(const span<_OtherTy, _OtherExtent>& _Other) noexcept
: _Mybase(_Other.size()), _Mydata(_Other.data()) {
: _Mybase(_Other.size(), _Other.data()) {
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
_STL_VERIFY(_Other.size() == _Extent,
Expand All @@ -523,15 +532,15 @@ public:
_STL_VERIFY(_Count <= this->size(), "Count out of range in span::first()");
}
#endif // _CONTAINER_DEBUG_LEVEL > 0
return span<element_type, _Count>{_Mydata, _Count};
return span<element_type, _Count>{this->_Mydata, _Count};
}

_NODISCARD constexpr auto first(const size_type _Count) const noexcept
/* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Count <= this->size(), "Count out of range in span::first(count)");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return span<element_type, dynamic_extent>{_Mydata, _Count};
return span<element_type, dynamic_extent>{this->_Mydata, _Count};
}

template <size_t _Count>
Expand All @@ -544,14 +553,14 @@ public:
_STL_VERIFY(_Count <= this->size(), "Count out of range in span::last()");
}
#endif // _CONTAINER_DEBUG_LEVEL > 0
return span<element_type, _Count>{_Mydata + (this->size() - _Count), _Count};
return span<element_type, _Count>{this->_Mydata + (this->size() - _Count), _Count};
}

_NODISCARD constexpr auto last(const size_type _Count) const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Count <= this->size(), "Count out of range in span::last(count)");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return span<element_type, dynamic_extent>{_Mydata + (this->size() - _Count), _Count};
return span<element_type, dynamic_extent>{this->_Mydata + (this->size() - _Count), _Count};
}

template <size_t _Offset, size_t _Count = dynamic_extent>
Expand All @@ -572,7 +581,7 @@ public:
#endif // _CONTAINER_DEBUG_LEVEL > 0
using _ReturnType = span<element_type,
_Count != dynamic_extent ? _Count : (_Extent != dynamic_extent ? _Extent - _Offset : dynamic_extent)>;
return _ReturnType{_Mydata + _Offset, _Count == dynamic_extent ? this->size() - _Offset : _Count};
return _ReturnType{this->_Mydata + _Offset, _Count == dynamic_extent ? this->size() - _Offset : _Count};
}

_NODISCARD constexpr auto subspan(const size_type _Offset, const size_type _Count = dynamic_extent) const noexcept
Expand All @@ -583,7 +592,7 @@ public:
"Count out of range in span::subspan(offset, count)");
#endif // _CONTAINER_DEBUG_LEVEL > 0
using _ReturnType = span<element_type, dynamic_extent>;
return _ReturnType{_Mydata + _Offset, _Count == dynamic_extent ? this->size() - _Offset : _Count};
return _ReturnType{this->_Mydata + _Offset, _Count == dynamic_extent ? this->size() - _Offset : _Count};
}

// [span.obs] Observers
Expand All @@ -604,40 +613,40 @@ public:
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Off < this->size(), "span index out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Mydata[_Off];
return this->_Mydata[_Off];
}

_NODISCARD constexpr reference front() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(this->size() > 0, "front of empty span");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Mydata[0];
return this->_Mydata[0];
}

_NODISCARD constexpr reference back() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(this->size() > 0, "back of empty span");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Mydata[this->size() - 1];
return this->_Mydata[this->size() - 1];
}

_NODISCARD constexpr pointer data() const noexcept {
return _Mydata;
return this->_Mydata;
}

// [span.iterators] Iterator support
_NODISCARD constexpr iterator begin() const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
return {_Mydata, _Mydata, _Mydata + this->size()};
return {this->_Mydata, this->_Mydata, this->_Mydata + this->size()};
#else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv
return {_Mydata};
return {this->_Mydata};
#endif // _ITERATOR_DEBUG_LEVEL
}

_NODISCARD constexpr iterator end() const noexcept {
const auto _End = _Mydata + this->size();
const auto _End = this->_Mydata + this->size();
#if _ITERATOR_DEBUG_LEVEL >= 1
return {_End, _Mydata, _End};
return {_End, this->_Mydata, _End};
#else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv
return {_End};
#endif // _ITERATOR_DEBUG_LEVEL
Expand All @@ -652,17 +661,15 @@ public:
}

_NODISCARD constexpr pointer _Unchecked_begin() const noexcept {
return _Mydata;
return this->_Mydata;
}

_NODISCARD constexpr pointer _Unchecked_end() const noexcept {
return _Mydata + this->size();
return this->_Mydata + this->size();
}

private:
using _Mybase = _Span_extent_type<_Extent>;

pointer _Mydata{nullptr};
using _Mybase = _Span_extent_type<_Ty, _Extent>;
};

// DEDUCTION GUIDES
Expand Down
6 changes: 6 additions & 0 deletions tests/std/tests/P0122R7_span/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@

using namespace std;

static_assert(is_standard_layout_v<span<int>>);
static_assert(is_standard_layout_v<span<int, 4>>);

static_assert(sizeof(span<int, 4>) == sizeof(void*));
static_assert(sizeof(span<int>) == sizeof(void*) + sizeof(size_t));

static_assert(is_same_v<decltype(dynamic_extent), const size_t>);
static_assert(dynamic_extent == static_cast<size_t>(-1));

Expand Down

0 comments on commit 51f0d5b

Please sign in to comment.