Fixes #4.
This commit is contained in:
Michael Schellenberger Costa 2020-01-18 04:23:11 +01:00 коммит произвёл Stephan T. Lavavej
Родитель e36c3bff61
Коммит b3598a4f0b
6 изменённых файлов: 750 добавлений и 34 удалений

Просмотреть файл

@ -171,6 +171,7 @@ set(HEADERS
${CMAKE_CURRENT_LIST_DIR}/inc/scoped_allocator
${CMAKE_CURRENT_LIST_DIR}/inc/set
${CMAKE_CURRENT_LIST_DIR}/inc/shared_mutex
${CMAKE_CURRENT_LIST_DIR}/inc/span
${CMAKE_CURRENT_LIST_DIR}/inc/sstream
${CMAKE_CURRENT_LIST_DIR}/inc/stack
${CMAKE_CURRENT_LIST_DIR}/inc/stdexcept

Просмотреть файл

@ -81,6 +81,7 @@
#include <regex>
#include <scoped_allocator>
#include <set>
#include <span>
#include <sstream>
#include <stack>
#include <stdexcept>

727
stl/inc/span Normal file
Просмотреть файл

@ -0,0 +1,727 @@
// span standard header
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#pragma once
#ifndef _SPAN_
#define _SPAN_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#if !_HAS_CXX20
#pragma message("The contents of <span> are available only with C++20 or later.")
#else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv
#include <cstddef>
#include <type_traits>
#include <xutility>
#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
_STD_BEGIN
inline constexpr size_t dynamic_extent = static_cast<size_t>(-1);
// STRUCT TEMPLATE _Span_iterator
template <class _Ty>
struct _Span_iterator {
#ifdef __cpp_lib_concepts
using iterator_concept = contiguous_iterator_tag;
#endif // __cpp_lib_concepts
using iterator_category = random_access_iterator_tag;
using value_type = remove_cv_t<_Ty>;
using difference_type = ptrdiff_t;
using pointer = _Ty*;
using reference = _Ty&;
_NODISCARD constexpr operator _Span_iterator<const _Ty>() const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
return {_Myptr, _Mybegin, _Myend};
#else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv
return {_Myptr};
#endif // _ITERATOR_DEBUG_LEVEL
}
_NODISCARD constexpr reference operator*() const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
_STL_VERIFY(_Mybegin, "cannot dereference value-initialized span iterator");
_STL_VERIFY(_Myptr < _Myend, "cannot dereference end span iterator");
#endif // _ITERATOR_DEBUG_LEVEL >= 1
return *_Myptr;
}
_NODISCARD constexpr pointer operator->() const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
_STL_VERIFY(_Mybegin, "cannot dereference value-initialized span iterator");
_STL_VERIFY(_Myptr < _Myend, "cannot dereference end span iterator");
#endif // _ITERATOR_DEBUG_LEVEL >= 1
return _Myptr;
}
constexpr _Span_iterator& operator++() noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
_STL_VERIFY(_Mybegin, "cannot increment value-initialized span iterator");
_STL_VERIFY(_Myptr < _Myend, "cannot increment span iterator past end");
#endif // _ITERATOR_DEBUG_LEVEL >= 1
++_Myptr;
return *this;
}
constexpr _Span_iterator operator++(int) noexcept {
_Span_iterator _Tmp{*this};
++*this;
return _Tmp;
}
constexpr _Span_iterator& operator--() noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
_STL_VERIFY(_Mybegin, "cannot decrement value-initialized span iterator");
_STL_VERIFY(_Mybegin < _Myptr, "cannot decrement span iterator before begin");
#endif // _ITERATOR_DEBUG_LEVEL >= 1
--_Myptr;
return *this;
}
constexpr _Span_iterator operator--(int) noexcept {
_Span_iterator _Tmp{*this};
--*this;
return _Tmp;
}
constexpr void _Verify_offset([[maybe_unused]] const difference_type _Off) const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
if (_Off != 0) {
_STL_VERIFY(_Mybegin, "cannot seek value-initialized span iterator");
}
if (_Off < 0) {
_STL_VERIFY(_Myptr - _Mybegin >= -_Off, "cannot seek span iterator before begin");
}
if (_Off > 0) {
_STL_VERIFY(_Myend - _Myptr >= _Off, "cannot seek span iterator after end");
}
#endif // _ITERATOR_DEBUG_LEVEL >= 1
}
constexpr _Span_iterator& operator+=(const difference_type _Off) noexcept {
_Verify_offset(_Off);
_Myptr += _Off;
return *this;
}
_NODISCARD constexpr _Span_iterator operator+(const difference_type _Off) const noexcept {
_Span_iterator _Tmp{*this};
_Tmp += _Off;
return _Tmp;
}
constexpr _Span_iterator& operator-=(const difference_type _Off) noexcept {
_Verify_offset(-_Off);
_Myptr -= _Off;
return *this;
}
_NODISCARD constexpr _Span_iterator operator-(const difference_type _Off) const noexcept {
_Span_iterator _Tmp{*this};
_Tmp -= _Off;
return _Tmp;
}
_NODISCARD constexpr difference_type operator-(const _Span_iterator& _Right) const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
_STL_VERIFY(
_Mybegin == _Right._Mybegin && _Myend == _Right._Myend, "cannot subtract incompatible span iterators");
#endif // _ITERATOR_DEBUG_LEVEL >= 1
return _Myptr - _Right._Myptr;
}
_NODISCARD constexpr reference operator[](const difference_type _Off) const noexcept {
return *(*this + _Off);
}
_NODISCARD constexpr bool operator==(const _Span_iterator& _Right) const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
_STL_VERIFY(_Mybegin == _Right._Mybegin && _Myend == _Right._Myend,
"cannot compare incompatible span iterators for equality");
#endif // _ITERATOR_DEBUG_LEVEL >= 1
return _Myptr == _Right._Myptr;
}
_NODISCARD constexpr bool operator!=(const _Span_iterator& _Right) const noexcept {
return !(*this == _Right);
}
_NODISCARD constexpr bool operator<(const _Span_iterator& _Right) const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
_STL_VERIFY(
_Mybegin == _Right._Mybegin && _Myend == _Right._Myend, "cannot compare incompatible span iterators");
#endif // _ITERATOR_DEBUG_LEVEL >= 1
return _Myptr < _Right._Myptr;
}
_NODISCARD constexpr bool operator>(const _Span_iterator& _Right) const noexcept {
return _Right < *this;
}
_NODISCARD constexpr bool operator<=(const _Span_iterator& _Right) const noexcept {
return !(_Right < *this);
}
_NODISCARD constexpr bool operator>=(const _Span_iterator& _Right) const noexcept {
return !(*this < _Right);
}
#if _ITERATOR_DEBUG_LEVEL >= 1
friend constexpr void _Verify_range(const _Span_iterator& _First, const _Span_iterator& _Last) noexcept {
_STL_VERIFY(_First._Mybegin == _Last._Mybegin && _First._Myend == _Last._Myend,
"span iterators from different views do not form a range");
_STL_VERIFY(_First._Myptr <= _Last._Myptr, "span iterator range transposed");
}
#endif // _ITERATOR_DEBUG_LEVEL >= 1
using _Prevent_inheriting_unwrap = _Span_iterator;
_NODISCARD constexpr pointer _Unwrapped() const noexcept {
return _Myptr;
}
static constexpr bool _Unwrap_when_unverified = _ITERATOR_DEBUG_LEVEL == 0;
constexpr void _Seek_to(const pointer _It) noexcept {
_Myptr = _It;
}
pointer _Myptr = nullptr;
#if _ITERATOR_DEBUG_LEVEL >= 1
pointer _Mybegin = nullptr;
pointer _Myend = nullptr;
#endif // _ITERATOR_DEBUG_LEVEL >= 1
};
template <class _Ty>
_NODISCARD _Span_iterator<_Ty> operator+(const ptrdiff_t _Off, _Span_iterator<_Ty> _Next) noexcept {
return _Next += _Off;
}
template <class _Ty>
struct pointer_traits<_Span_iterator<_Ty>> {
using pointer = _Span_iterator<_Ty>;
using element_type = _Ty;
using difference_type = ptrdiff_t;
_NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept {
return _Iter._Unwrapped();
}
};
// STRUCT TEMPLATE _Span_extent_type
template <size_t _Extent>
struct _Span_extent_type {
constexpr _Span_extent_type() noexcept = default;
constexpr explicit _Span_extent_type(size_t) noexcept {}
_NODISCARD constexpr size_t size() const noexcept {
return _Extent;
}
};
template <>
struct _Span_extent_type<dynamic_extent> {
constexpr _Span_extent_type() noexcept = default;
constexpr explicit _Span_extent_type(const size_t _Size) noexcept : _Mysize(_Size) {}
_NODISCARD constexpr size_t size() const noexcept {
return _Mysize;
}
private:
size_t _Mysize{0};
};
template <class _Ty, size_t _Size>
class array;
template <class _Ty, size_t _Extent>
class span;
#ifdef __cpp_lib_concepts
namespace ranges {
template <class _Ty, size_t _Extent>
inline constexpr bool enable_safe_range<span<_Ty, _Extent>> = true;
} // namespace ranges
// VARIABLE TEMPLATE _Is_span_v
template <class>
inline constexpr bool _Is_span_v = false;
template <class _Ty, size_t _Extent>
inline constexpr bool _Is_span_v<span<_Ty, _Extent>> = true;
// VARIABLE TEMPLATE _Is_std_array_v
template <class>
inline constexpr bool _Is_std_array_v = false;
template <class _Ty, size_t _Size>
inline constexpr bool _Is_std_array_v<array<_Ty, _Size>> = true;
// clang-format off
template <class _It, class _Ty>
concept _Is_span_compatible_iterator = contiguous_iterator<_It>
&& is_convertible_v<remove_reference_t<iter_reference_t<_It>>(*)[], _Ty(*)[]>;
template <class _Sentinel, class _It>
concept _Is_span_compatible_sentinel = sized_sentinel_for<_Sentinel, _It>
&& !is_convertible_v<_Sentinel, size_t>;
template <class _Rng, class _Ty>
concept _Is_span_compatible_range =
!is_array_v<remove_cvref_t<_Rng>>
&& !_Is_span_v<remove_cvref_t<_Rng>>
&& !_Is_std_array_v<remove_cvref_t<_Rng>>
&& _RANGES contiguous_range<_Rng>
&& _RANGES sized_range<_Rng>
&& (_RANGES safe_range<_Rng> || is_const_v<_Ty>)
&& is_convertible_v<remove_reference_t<_RANGES range_reference_t<_Rng>>(*)[], _Ty(*)[]>;
// clang-format on
#else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv
// STRUCT TEMPLATE _Is_span
template <class>
struct _Is_span : false_type {};
template <class _Ty, size_t _Extent>
struct _Is_span<span<_Ty, _Extent>> : true_type {};
// STRUCT TEMPLATE _Is_std_array
template <class>
struct _Is_std_array : false_type {};
template <class _Ty, size_t _Size>
struct _Is_std_array<array<_Ty, _Size>> : true_type {};
// STRUCT TEMPLATE _Is_span_convertible_range
template <class _Rng, class _Ty>
struct _Is_span_convertible_range
: bool_constant<is_convertible_v<remove_pointer_t<decltype(_STD data(_STD declval<_Rng&>()))> (*)[], _Ty (*)[]>> {};
// STRUCT TEMPLATE _Has_container_interface
template <class, class = void>
struct _Has_container_interface : false_type {};
template <class _Rng>
struct _Has_container_interface<_Rng,
void_t<decltype(_STD data(_STD declval<_Rng&>())), decltype(_STD size(_STD declval<_Rng&>()))>> : true_type {};
// STRUCT TEMPLATE _Is_span_compatible_range
// clang-format off
template <class _Rng, class _Ty>
struct _Is_span_compatible_range : bool_constant<conjunction_v<
negation<is_array<_Rng>>,
negation<_Is_span<remove_const_t<_Rng>>>,
negation<_Is_std_array<remove_const_t<_Rng>>>,
_Has_container_interface<_Rng>,
_Is_span_convertible_range<_Rng, _Ty>>> {};
// clang-format on
#endif // !__cpp_lib_concepts
// [views.span]
// CLASS TEMPLATE span
template <class _Ty, size_t _Extent = dynamic_extent>
class span : public _Span_extent_type<_Extent> {
public:
using element_type = _Ty;
using value_type = remove_cv_t<_Ty>;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = _Ty*;
using const_pointer = const _Ty*;
using reference = _Ty&;
using const_reference = const _Ty&;
using iterator = _Span_iterator<_Ty>;
using const_iterator = _Span_iterator<const _Ty>;
using reverse_iterator = _STD reverse_iterator<iterator>;
using const_reverse_iterator = _STD reverse_iterator<const_iterator>;
static constexpr size_type extent = _Extent;
// [span.cons] Constructors, copy, and assignment
#ifdef __cpp_lib_concepts
// clang-format off
constexpr span() noexcept requires (_Extent == 0 || _Extent == dynamic_extent) = default;
template <_Is_span_compatible_iterator<element_type> _It>
constexpr span(_It _First, size_type _Count) noexcept // strengthened
: _Mybase(_Count), _Mydata(_STD to_address(_Get_unwrapped_n(_First, _Count))) {
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
_STL_VERIFY(_Count == _Extent, "span construction from invalid range as count != extent");
}
#endif // _CONTAINER_DEBUG_LEVEL > 0
}
template <_Is_span_compatible_iterator<element_type> _It, _Is_span_compatible_sentinel<_It> _Sentinel>
constexpr span(_It _First, _Sentinel _Last) noexcept(noexcept(_Last - _First)) // strengthened
: _Mybase(static_cast<size_type>(_Last - _First)), _Mydata(_STD to_address(_First)) {
_Adl_verify_range(_First, _Last);
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
_STL_VERIFY(_Last - _First == _Extent, "span construction from invalid range as last - first != extent");
}
#endif // _CONTAINER_DEBUG_LEVEL > 0
}
template <size_t _Size>
requires (_Extent == dynamic_extent || _Extent == _Size)
constexpr span(type_identity_t<element_type> (&_Arr)[_Size]) noexcept : _Mybase(_Size), _Mydata(_Arr) {}
template <size_t _Size>
requires (_Extent == dynamic_extent || _Extent == _Size)
constexpr span(array<value_type, _Size>& _Arr) noexcept : _Mybase(_Size), _Mydata(_Arr.data()) {}
template <size_t _Size>
requires (_Extent == dynamic_extent || _Extent == _Size) && is_convertible_v<const value_type*, element_type*>
constexpr span(const array<value_type, _Size>& _Arr) noexcept : _Mybase(_Size), _Mydata(_Arr.data()) {}
template <class _Rng>
requires (_Extent == dynamic_extent) && _Is_span_compatible_range<_Rng, element_type>
constexpr span(_Rng&& _Range)
: _Mybase(static_cast<size_type>(_RANGES size(_Range))), _Mydata(_RANGES data(_Range)) {}
template <class _OtherTy, size_t _OtherExtent>
requires (_Extent == dynamic_extent || _Extent == _OtherExtent)
&& is_convertible_v<_OtherTy (*)[], element_type (*)[]>
constexpr span(const span<_OtherTy, _OtherExtent>& _Other) noexcept
: _Mybase(_Other.size()), _Mydata(_Other.data()) {}
// clang-format on
#else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv
template <size_t _Ext = _Extent, enable_if_t<_Ext == 0 || _Ext == dynamic_extent, int> = 0>
constexpr span() noexcept {}
constexpr span(pointer _Ptr, size_type _Count) noexcept // strengthened
: _Mybase(_Count), _Mydata(_Ptr) {
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
_STL_VERIFY(_Count == _Extent, "span construction from invalid range as count != extent");
}
#endif // _CONTAINER_DEBUG_LEVEL > 0
}
constexpr span(pointer _First, pointer _Last) noexcept // strengthened
: _Mybase(static_cast<size_type>(_Last - _First)), _Mydata(_First) {
_Adl_verify_range(_First, _Last);
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (_Extent != dynamic_extent) {
_STL_VERIFY(_Last - _First == _Extent, "span construction from invalid range as last - first != extent");
}
#endif // _CONTAINER_DEBUG_LEVEL > 0
}
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) {}
template <size_t _Size, enable_if_t<_Extent == dynamic_extent || _Extent == _Size, int> = 0>
constexpr span(array<value_type, _Size>& _Arr) noexcept : _Mybase(_Size), _Mydata(_Arr.data()) {}
template <size_t _Size, size_t _Ext = _Extent,
enable_if_t<conjunction_v<bool_constant<_Ext == dynamic_extent || _Ext == _Size>,
is_convertible<const value_type*, element_type*>>,
int> = 0>
constexpr span(const array<value_type, _Size>& _Arr) noexcept : _Mybase(_Size), _Mydata(_Arr.data()) {}
template <class _Rng, enable_if_t<conjunction_v<bool_constant<_Extent == dynamic_extent>,
_Is_span_compatible_range<_Rng, element_type>>,
int> = 0>
constexpr span(_Rng& _Range) : _Mybase(static_cast<size_type>(_STD size(_Range))), _Mydata(_STD data(_Range)) {}
template <class _Rng, enable_if_t<conjunction_v<bool_constant<_Extent == dynamic_extent>,
_Is_span_compatible_range<const _Rng, element_type>>,
int> = 0>
constexpr span(const _Rng& _Range)
: _Mybase(static_cast<size_type>(_STD size(_Range))), _Mydata(_STD data(_Range)) {}
template <class _OtherTy, size_t _OtherExtent,
enable_if_t<conjunction_v<bool_constant<_Extent == dynamic_extent || _Extent == _OtherExtent>,
is_convertible<_OtherTy (*)[], element_type (*)[]>>,
int> = 0>
constexpr span(const span<_OtherTy, _OtherExtent>& _Other) noexcept
: _Mybase(_Other.size()), _Mydata(_Other.data()) {}
#endif // !__cpp_lib_concepts
// [span.sub] Subviews
template <size_t _Count>
_NODISCARD constexpr span<element_type, _Count> first() const noexcept /* strengthened */ {
if constexpr (_Extent != dynamic_extent) {
static_assert(_Count <= _Extent, "Count out of range in span::first()");
}
#if _CONTAINER_DEBUG_LEVEL > 0
else {
_STL_VERIFY(_Count <= this->size(), "Count out of range in span::first()");
}
#endif // _CONTAINER_DEBUG_LEVEL > 0
return {_Mydata, _Count};
}
_NODISCARD constexpr span<element_type, dynamic_extent> 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 {_Mydata, _Count};
}
template <size_t _Count>
_NODISCARD constexpr span<element_type, _Count> last() const noexcept /* strengthened */ {
if constexpr (_Extent != dynamic_extent) {
static_assert(_Count <= _Extent, "Count out of range in span::last()");
}
#if _CONTAINER_DEBUG_LEVEL > 0
else {
_STL_VERIFY(_Count <= this->size(), "Count out of range in span::last()");
}
#endif // _CONTAINER_DEBUG_LEVEL > 0
return {_Mydata + (this->size() - _Count), _Count};
}
_NODISCARD constexpr span<element_type, dynamic_extent> 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 {_Mydata + (this->size() - _Count), _Count};
}
template <size_t _Offset, size_t _Count = dynamic_extent>
_NODISCARD constexpr span<element_type,
_Count != dynamic_extent ? _Count : (_Extent != dynamic_extent ? _Extent - _Offset : dynamic_extent)>
subspan() const noexcept /* strengthened */ {
if constexpr (_Extent != dynamic_extent) {
static_assert(_Offset <= _Extent, "Offset out of range in span::subspan()");
static_assert(
_Count == dynamic_extent || _Count <= _Extent - _Offset, "Count out of range in span::subspan()");
}
#if _CONTAINER_DEBUG_LEVEL > 0
else {
_STL_VERIFY(_Offset <= this->size(), "Offset out of range in span::subspan()");
if constexpr (_Count != dynamic_extent) {
_STL_VERIFY(_Count <= this->size() - _Offset, "Count out of range in span::subspan()");
}
}
#endif // _CONTAINER_DEBUG_LEVEL > 0
return {_Mydata + _Offset, _Count == dynamic_extent ? this->size() - _Offset : _Count};
}
_NODISCARD constexpr span<element_type, dynamic_extent> subspan(
const size_type _Offset, const size_type _Count = dynamic_extent) const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Offset <= this->size(), "Offset out of range in span::subspan(offset, count)");
_STL_VERIFY(_Count == dynamic_extent || _Count <= this->size() - _Offset,
"Count out of range in span::subspan(offset, count)");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return {_Mydata + _Offset, _Count == dynamic_extent ? this->size() - _Offset : _Count};
}
// [span.obs] Observers
_NODISCARD constexpr size_type size_bytes() const noexcept {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(this->size() <= dynamic_extent / sizeof(element_type),
"size of span in bytes exceeds std::numeric_limits<size_t>::max()");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return this->size() * sizeof(element_type);
}
_NODISCARD constexpr bool empty() const noexcept {
return this->size() == 0;
}
// [span.elem] Element access
_NODISCARD constexpr reference operator[](const size_type _Off) const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Off < this->size(), "span index out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _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];
}
_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];
}
_NODISCARD constexpr pointer data() const noexcept {
return _Mydata;
}
// [span.iterators] Iterator support
_NODISCARD constexpr iterator begin() const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
return {_Mydata, _Mydata, _Mydata + this->size()};
#else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv
return {_Mydata};
#endif // _ITERATOR_DEBUG_LEVEL
}
_NODISCARD constexpr iterator end() const noexcept {
const auto _End = _Mydata + this->size();
#if _ITERATOR_DEBUG_LEVEL >= 1
return {_End, _Mydata, _End};
#else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv
return {_End};
#endif // _ITERATOR_DEBUG_LEVEL
}
_NODISCARD constexpr const_iterator cbegin() const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
return {_Mydata, _Mydata, _Mydata + this->size()};
#else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv
return {_Mydata};
#endif // _ITERATOR_DEBUG_LEVEL
}
_NODISCARD constexpr const_iterator cend() const noexcept {
const auto _End = _Mydata + this->size();
#if _ITERATOR_DEBUG_LEVEL >= 1
return {_End, _Mydata, _End};
#else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv
return {_End};
#endif // _ITERATOR_DEBUG_LEVEL
}
_NODISCARD constexpr reverse_iterator rbegin() const noexcept {
return reverse_iterator{end()};
}
_NODISCARD constexpr reverse_iterator rend() const noexcept {
return reverse_iterator{begin()};
}
_NODISCARD constexpr const_reverse_iterator crbegin() const noexcept {
return const_reverse_iterator{cend()};
}
_NODISCARD constexpr const_reverse_iterator crend() const noexcept {
return const_reverse_iterator{cbegin()};
}
_NODISCARD constexpr pointer _Unchecked_begin() const noexcept {
return _Mydata;
}
_NODISCARD constexpr pointer _Unchecked_end() const noexcept {
return _Mydata + this->size();
}
private:
using _Mybase = _Span_extent_type<_Extent>;
pointer _Mydata{nullptr};
};
// DEDUCTION GUIDES
template <class _Ty, size_t _Extent>
span(_Ty (&)[_Extent])->span<_Ty, _Extent>;
template <class _Ty, size_t _Size>
span(array<_Ty, _Size>&)->span<_Ty, _Size>;
template <class _Ty, size_t _Size>
span(const array<_Ty, _Size>&)->span<const _Ty, _Size>;
#ifdef __cpp_lib_concepts
template <contiguous_iterator _It, class _End>
span(_It, _End)->span<remove_reference_t<iter_reference_t<_It>>>;
template <_RANGES contiguous_range _Rng>
span(_Rng &&)->span<remove_reference_t<_RANGES range_reference_t<_Rng>>>;
#else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv
template <class _Rng>
span(_Rng&)->span<typename _Rng::value_type>;
template <class _Rng>
span(const _Rng&)->span<const typename _Rng::value_type>;
#endif // !__cpp_lib_concepts
#if _HAS_STD_BYTE
// [span.objectrep] Views of object representation
// FUNCTION TEMPLATE as_bytes
template <class _Ty, size_t _Extent>
_NODISCARD auto as_bytes(span<_Ty, _Extent> _Sp) noexcept
-> span<const byte, _Extent == dynamic_extent ? dynamic_extent : sizeof(_Ty) * _Extent> {
return {reinterpret_cast<const byte*>(_Sp.data()), _Sp.size_bytes()};
}
// FUNCTION TEMPLATE as_writable_bytes
template <class _Ty, size_t _Extent, enable_if_t<!is_const_v<_Ty>, int> = 0>
_NODISCARD auto as_writable_bytes(span<_Ty, _Extent> _Sp) noexcept
-> span<byte, _Extent == dynamic_extent ? dynamic_extent : sizeof(_Ty) * _Extent> {
return {reinterpret_cast<byte*>(_Sp.data()), _Sp.size_bytes()};
}
#endif // _HAS_STD_BYTE
// [span.tuple] Tuple interface
#ifdef __cpp_lib_concepts
// clang-format off
template <class _Ty, size_t _Extent>
requires (_Extent != dynamic_extent)
struct tuple_size<span<_Ty, _Extent>> : integral_constant<size_t, _Extent> {};
// clang-format on
#else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv
template <class _Ty, size_t _Extent>
struct tuple_size<span<_Ty, _Extent>> : integral_constant<size_t, _Extent> {};
template <class _Ty>
struct tuple_size<span<_Ty, dynamic_extent>>;
#endif // !__cpp_lib_concepts
template <size_t _Index, class _Ty, size_t _Extent>
struct tuple_element<_Index, span<_Ty, _Extent>> {
static_assert(dynamic_extent != _Extent, "std::span<T, dynamic_extent> is not tuple-like");
static_assert(_Index < _Extent, "Index out of bounds for a std::span of this extent");
using type = _Ty;
};
template <size_t _Index, class _Ty, size_t _Extent>
_NODISCARD constexpr _Ty& get(span<_Ty, _Extent> _Span) noexcept {
static_assert(dynamic_extent != _Extent, "std::get<> not supported for std::span<T, dynamic_extent>");
static_assert(_Index < _Extent, "Index out of bounds for a std::span of this extent");
return _Span[_Index];
}
_STD_END
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // _HAS_CXX20
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _SPAN_

Просмотреть файл

@ -139,8 +139,9 @@ _NODISCARD constexpr _Ty* to_address(_Ty* const _Val) noexcept {
return _Val;
}
// constexpr per pending LWG issue, submitted 2020-01-14
template <class _Ptr>
_NODISCARD auto to_address(const _Ptr& _Val) noexcept {
_NODISCARD constexpr auto to_address(const _Ptr& _Val) noexcept {
if constexpr (_Has_to_address_v<_Ptr>) {
return pointer_traits<_Ptr>::to_address(_Val);
} else {

Просмотреть файл

@ -127,6 +127,7 @@
// _HAS_CXX20 directly controls:
// P0020R6 atomic<float>, atomic<double>, atomic<long double>
// P0122R7 <span>
// P0318R1 unwrap_reference, unwrap_ref_decay
// P0325R4 to_array()
// P0356R5 bind_front()
@ -161,10 +162,12 @@
// P0919R3 Heterogeneous Lookup For Unordered Containers
// P0966R1 string::reserve() Should Not Shrink
// P1006R1 constexpr For pointer_traits<T*>::pointer_to()
// P1024R3 Enhancing span Usability
// P1085R2 Removing span Comparisons
// P1209R0 erase_if(), erase()
// P1227R2 Signed std::ssize(), Unsigned span::size()
// (partially implemented)
// P1357R1 is_bounded_array, is_unbounded_array
// P1394R4 Range Constructor For span
// P1456R1 Move-Only Views
// P1612R1 Relocating endian To <bit>
// P1645R1 constexpr For <numeric> Algorithms
@ -172,6 +175,7 @@
// P1690R1 Refining Heterogeneous Lookup For Unordered Containers
// P1754R1 Rename Concepts To standard_case
// P1870R1 safe_range
// P1872R0 span Should Have size_type, Not index_type
// P1959R0 Removing weak_equality And strong_equality
// P????R? directory_entry::clear_cache()
@ -1012,6 +1016,7 @@
#define __cpp_lib_math_constants 201907L
#define __cpp_lib_remove_cvref 201711L
#define __cpp_lib_shift 201806L
#define __cpp_lib_span 201902L
#define __cpp_lib_ssize 201902L
#define __cpp_lib_starts_ends_with 201711L
#define __cpp_lib_to_address 201711L

Просмотреть файл

@ -196,38 +196,6 @@ utilities\tuple\tuple.tuple\tuple.apply\apply_large_arity.pass.cpp
# C++20 P0019R8 "atomic_ref"
language.support\support.limits\support.limits.general\atomic.version.pass.cpp
# C++20 P0122R7 "<span>" (and subsequent patch papers)
containers\views\types.pass.cpp
containers\views\span.cons\array.pass.cpp
containers\views\span.cons\assign.pass.cpp
containers\views\span.cons\container.pass.cpp
containers\views\span.cons\copy.pass.cpp
containers\views\span.cons\deduct.pass.cpp
containers\views\span.cons\default.pass.cpp
containers\views\span.cons\ptr_len.pass.cpp
containers\views\span.cons\ptr_ptr.pass.cpp
containers\views\span.cons\span.pass.cpp
containers\views\span.cons\stdarray.pass.cpp
containers\views\span.elem\back.pass.cpp
containers\views\span.elem\data.pass.cpp
containers\views\span.elem\front.pass.cpp
containers\views\span.elem\op_idx.pass.cpp
containers\views\span.iterators\begin.pass.cpp
containers\views\span.iterators\end.pass.cpp
containers\views\span.iterators\rbegin.pass.cpp
containers\views\span.iterators\rend.pass.cpp
containers\views\span.objectrep\as_bytes.pass.cpp
containers\views\span.objectrep\as_writable_bytes.pass.cpp
containers\views\span.obs\empty.pass.cpp
containers\views\span.obs\size.pass.cpp
containers\views\span.obs\size_bytes.pass.cpp
containers\views\span.sub\first.pass.cpp
containers\views\span.sub\last.pass.cpp
containers\views\span.sub\subspan.pass.cpp
containers\views\span.tuple\get.pass.cpp
containers\views\span.tuple\tuple_element.pass.cpp
containers\views\span.tuple\tuple_size.pass.cpp
# C++20 P0202R3 "constexpr For <algorithm> And exchange()"
algorithms\alg.modifying.operations\alg.copy\copy_backward.pass.cpp
algorithms\alg.modifying.operations\alg.copy\copy_if.pass.cpp
@ -303,6 +271,9 @@ algorithms\alg.sorting\alg.sort\is.sorted\is_sorted_comp.pass.cpp
algorithms\alg.sorting\alg.sort\is.sorted\is_sorted_until_comp.pass.cpp
algorithms\alg.sorting\alg.sort\is.sorted\is_sorted_until.pass.cpp
algorithms\alg.sorting\alg.sort\is.sorted\is_sorted.pass.cpp
containers\views\span.sub\first.pass.cpp
containers\views\span.sub\last.pass.cpp
containers\views\span.sub\subspan.pass.cpp
utilities\utility\exchange\exchange.pass.cpp
# C++20 P0355R7 "<chrono> Calendars And Time Zones"
@ -608,6 +579,10 @@ utilities\tuple\tuple.tuple\tuple.cnstr\test_lazy_sfinae.pass.cpp
# Compiler bug: VSO-406936 "is_constructible<int&&, double&> and is_constructible<const int&, ExplicitTo<int&&>> should be true"
utilities\meta\meta.unary\meta.unary.prop\is_constructible.pass.cpp
# Compiler bug: DevCom-876860 "conditional operator errors" blocks readable<volatile int*>.
containers\views\span.cons\ptr_len.pass.cpp
containers\views\span.cons\ptr_ptr.pass.cpp
# *** CLANG COMPILER BUGS ***
# LLVM-33230 "Clang on Windows should define __STDCPP_THREADS__ to be 1"
@ -617,6 +592,12 @@ thread\macro.pass.cpp
iterators\iterator.primitives\iterator.traits\pointer.pass.cpp
iterators\iterator.primitives\std.iterator.tags\contiguous_iterator_tag.pass.cpp
# Clang 9 doesn't support comparison rewriting; implemented in Clang 10.
containers\views\span.iterators\begin.pass.cpp
containers\views\span.iterators\end.pass.cpp
containers\views\span.iterators\rbegin.pass.cpp
containers\views\span.iterators\rend.pass.cpp
# *** CLANG ISSUES, NOT YET ANALYZED ***
# Clang doesn't enable sized deallocation by default. Should we add -fsized-deallocation or do something else?