From 51f0d5b795dce5a88fe9ae430f55350b43837363 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Wed, 3 Jun 2020 15:13:08 +0200 Subject: [PATCH] [span] Make span standard_layout --- stl/inc/span | 89 +++++++++++++++------------ tests/std/tests/P0122R7_span/test.cpp | 6 ++ 2 files changed, 54 insertions(+), 41 deletions(-) diff --git a/stl/inc/span b/stl/inc/span index ae61ffef161..cfbee3526dc 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -226,29 +226,38 @@ struct pointer_traits<_Span_iterator<_Ty>> { }; // STRUCT TEMPLATE _Span_extent_type -template +template 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 { +template +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 @@ -346,7 +355,7 @@ inline constexpr bool _Is_span_compatible_range = conjunction_v< // [views.span] // CLASS TEMPLATE span template -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>; @@ -369,7 +378,7 @@ public: template <_Span_compatible_iterator _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, @@ -381,7 +390,7 @@ public: template <_Span_compatible_iterator _It, _Span_compatible_sentinel<_It> _Sentinel> constexpr explicit(_Extent != dynamic_extent) span(_It _First, _Sentinel _Last) noexcept(noexcept(_Last - _First)) // strengthened - : _Mybase(static_cast(_Last - _First)), _Mydata(_STD to_address(_First)) { + : _Mybase(static_cast(_Last - _First),_STD to_address(_First)) { _Adl_verify_range(_First, _Last); #if _CONTAINER_DEBUG_LEVEL > 0 if constexpr (_Extent != dynamic_extent) { @@ -393,21 +402,21 @@ public: template requires (_Extent == dynamic_extent || _Extent == _Size) - constexpr span(type_identity_t (&_Arr)[_Size]) noexcept : _Mybase(_Size), _Mydata(_Arr) {} + constexpr span(type_identity_t (&_Arr)[_Size]) noexcept : _Mybase(_Size, _Arr) {} template 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 requires (_Extent == dynamic_extent || _Extent == _Size) && is_convertible_v - 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 _Rng> constexpr explicit(_Extent != dynamic_extent) span(_Rng&& _Range) - : _Mybase(static_cast(_RANGES size(_Range))), _Mydata(_RANGES data(_Range)) { + : _Mybase(static_cast(_RANGES size(_Range)), _RANGES data(_Range)) { #if _CONTAINER_DEBUG_LEVEL > 0 if constexpr (_Extent != dynamic_extent) { _STL_VERIFY(_RANGES size(_Range) == _Extent, @@ -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, @@ -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, @@ -447,7 +456,7 @@ public: } constexpr explicit(_Extent != dynamic_extent) span(pointer _First, pointer _Last) noexcept // strengthened - : _Mybase(static_cast(_Last - _First)), _Mydata(_First) { + : _Mybase(static_cast(_Last - _First), _First) { _Adl_verify_range(_First, _Last); #if _CONTAINER_DEBUG_LEVEL > 0 if constexpr (_Extent != dynamic_extent) { @@ -458,23 +467,23 @@ public: } template = 0> - constexpr span(element_type (&_Arr)[_Size]) noexcept : _Mybase(_Size), _Mydata(_Arr) {} + constexpr span(element_type (&_Arr)[_Size]) noexcept : _Mybase(_Size, _Arr) {} template , 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 , is_convertible>, 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 , int> = 0> constexpr explicit(_Extent != dynamic_extent) span(_Rng& _Range) - : _Mybase(static_cast(_STD size(_Range))), _Mydata(_STD data(_Range)) { + : _Mybase(static_cast(_STD size(_Range)), _STD data(_Range)) { #if _CONTAINER_DEBUG_LEVEL > 0 if constexpr (_Extent != dynamic_extent) { _STL_VERIFY(_STD size(_Range) == _Extent, @@ -485,7 +494,7 @@ public: template , int> = 0> constexpr explicit(_Extent != dynamic_extent) span(const _Rng& _Range) - : _Mybase(static_cast(_STD size(_Range))), _Mydata(_STD data(_Range)) { + : _Mybase(static_cast(_STD size(_Range)), _STD data(_Range)) { #if _CONTAINER_DEBUG_LEVEL > 0 if constexpr (_Extent != dynamic_extent) { _STL_VERIFY(_STD size(_Range) == _Extent, @@ -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, @@ -523,7 +532,7 @@ public: _STL_VERIFY(_Count <= this->size(), "Count out of range in span::first()"); } #endif // _CONTAINER_DEBUG_LEVEL > 0 - return span{_Mydata, _Count}; + return span{this->_Mydata, _Count}; } _NODISCARD constexpr auto first(const size_type _Count) const noexcept @@ -531,7 +540,7 @@ public: #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{_Mydata, _Count}; + return span{this->_Mydata, _Count}; } template @@ -544,14 +553,14 @@ public: _STL_VERIFY(_Count <= this->size(), "Count out of range in span::last()"); } #endif // _CONTAINER_DEBUG_LEVEL > 0 - return span{_Mydata + (this->size() - _Count), _Count}; + return span{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{_Mydata + (this->size() - _Count), _Count}; + return span{this->_Mydata + (this->size() - _Count), _Count}; } template @@ -572,7 +581,7 @@ public: #endif // _CONTAINER_DEBUG_LEVEL > 0 using _ReturnType = span; - 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 @@ -583,7 +592,7 @@ public: "Count out of range in span::subspan(offset, count)"); #endif // _CONTAINER_DEBUG_LEVEL > 0 using _ReturnType = span; - 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 @@ -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 @@ -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 diff --git a/tests/std/tests/P0122R7_span/test.cpp b/tests/std/tests/P0122R7_span/test.cpp index 03b9cc8b738..3e36d080173 100644 --- a/tests/std/tests/P0122R7_span/test.cpp +++ b/tests/std/tests/P0122R7_span/test.cpp @@ -16,6 +16,12 @@ using namespace std; +static_assert(is_standard_layout_v>); +static_assert(is_standard_layout_v>); + +static_assert(sizeof(span) == sizeof(void*)); +static_assert(sizeof(span) == sizeof(void*) + sizeof(size_t)); + static_assert(is_same_v); static_assert(dynamic_extent == static_cast(-1));