mirror of
				https://github.com/KartKrewDev/RingRacers.git
				synced 2025-10-30 08:01:28 +00:00 
			
		
		
		
	Add tcbrindle's C++20 std::span impl (tcb::span)
This commit is contained in:
		
							parent
							
								
									41ebd7c67d
								
							
						
					
					
						commit
						ccb74e7371
					
				
					 4 changed files with 630 additions and 0 deletions
				
			
		|  | @ -224,6 +224,8 @@ target_link_libraries(SRB2SDL2 PRIVATE DiscordRPC::DiscordRPC) | |||
| target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_DISCORDRPC -DUSE_STUN) | ||||
| target_sources(SRB2SDL2 PRIVATE discord.c stun.c) | ||||
| 
 | ||||
| target_link_libraries(SRB2SDL2 PRIVATE tcbrindle::span) | ||||
| 
 | ||||
| set(SRB2_HAVE_THREADS ON) | ||||
| target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_THREADS) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								thirdparty/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								thirdparty/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							|  | @ -540,3 +540,5 @@ if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}") | |||
| 	target_include_directories(discord-rpc INTERFACE "${DiscordRPC_SOURCE_DIR}/include") | ||||
| 	add_library(DiscordRPC::DiscordRPC ALIAS discord-rpc) | ||||
| endif() | ||||
| 
 | ||||
| add_subdirectory(tcbrindle_span) | ||||
|  |  | |||
							
								
								
									
										8
									
								
								thirdparty/tcbrindle_span/CMakeLists.txt
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								thirdparty/tcbrindle_span/CMakeLists.txt
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| # https://github.com/tcbrindle/span/ | ||||
| # Portable implementation of C++20 std::span | ||||
| # Boost License 1.0 | ||||
| 
 | ||||
| add_library(tcbrindle_span INTERFACE include/tcb/span.hpp) | ||||
| target_include_directories(tcbrindle_span INTERFACE include) | ||||
| 
 | ||||
| add_library(tcbrindle::span ALIAS tcbrindle_span) | ||||
							
								
								
									
										618
									
								
								thirdparty/tcbrindle_span/include/tcb/span.hpp
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										618
									
								
								thirdparty/tcbrindle_span/include/tcb/span.hpp
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,618 @@ | |||
| 
 | ||||
| /*
 | ||||
| This is an implementation of C++20's std::span | ||||
| http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf
 | ||||
| */ | ||||
| 
 | ||||
| //          Copyright Tristan Brindle 2018.
 | ||||
| // Distributed under the Boost Software License, Version 1.0.
 | ||||
| //    (See accompanying file ../../LICENSE_1_0.txt or copy at
 | ||||
| //          https://www.boost.org/LICENSE_1_0.txt)
 | ||||
| 
 | ||||
| #ifndef TCB_SPAN_HPP_INCLUDED | ||||
| #define TCB_SPAN_HPP_INCLUDED | ||||
| 
 | ||||
| #include <array> | ||||
| #include <cstddef> | ||||
| #include <cstdint> | ||||
| #include <type_traits> | ||||
| 
 | ||||
| #ifndef TCB_SPAN_NO_EXCEPTIONS | ||||
| // Attempt to discover whether we're being compiled with exception support
 | ||||
| #if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) | ||||
| #define TCB_SPAN_NO_EXCEPTIONS | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifndef TCB_SPAN_NO_EXCEPTIONS | ||||
| #include <cstdio> | ||||
| #include <stdexcept> | ||||
| #endif | ||||
| 
 | ||||
| // Various feature test macros
 | ||||
| 
 | ||||
| #ifndef TCB_SPAN_NAMESPACE_NAME | ||||
| #define TCB_SPAN_NAMESPACE_NAME tcb | ||||
| #endif | ||||
| 
 | ||||
| #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) | ||||
| #define TCB_SPAN_HAVE_CPP17 | ||||
| #endif | ||||
| 
 | ||||
| #if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) | ||||
| #define TCB_SPAN_HAVE_CPP14 | ||||
| #endif | ||||
| 
 | ||||
| namespace TCB_SPAN_NAMESPACE_NAME { | ||||
| 
 | ||||
| // Establish default contract checking behavior
 | ||||
| #if !defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) &&                          \ | ||||
|     !defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) &&                      \ | ||||
|     !defined(TCB_SPAN_NO_CONTRACT_CHECKING) | ||||
| #if defined(NDEBUG) || !defined(TCB_SPAN_HAVE_CPP14) | ||||
| #define TCB_SPAN_NO_CONTRACT_CHECKING | ||||
| #else | ||||
| #define TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) | ||||
| struct contract_violation_error : std::logic_error { | ||||
|     explicit contract_violation_error(const char* msg) : std::logic_error(msg) | ||||
|     {} | ||||
| }; | ||||
| 
 | ||||
| inline void contract_violation(const char* msg) | ||||
| { | ||||
|     throw contract_violation_error(msg); | ||||
| } | ||||
| 
 | ||||
| #elif defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) | ||||
| [[noreturn]] inline void contract_violation(const char* /*unused*/) | ||||
| { | ||||
|     std::terminate(); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #if !defined(TCB_SPAN_NO_CONTRACT_CHECKING) | ||||
| #define TCB_SPAN_STRINGIFY(cond) #cond | ||||
| #define TCB_SPAN_EXPECT(cond)                                                  \ | ||||
|     cond ? (void) 0 : contract_violation("Expected " TCB_SPAN_STRINGIFY(cond)) | ||||
| #else | ||||
| #define TCB_SPAN_EXPECT(cond) | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_inline_variables) | ||||
| #define TCB_SPAN_INLINE_VAR inline | ||||
| #else | ||||
| #define TCB_SPAN_INLINE_VAR | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TCB_SPAN_HAVE_CPP14) ||                                            \ | ||||
|     (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) | ||||
| #define TCB_SPAN_HAVE_CPP14_CONSTEXPR | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR) | ||||
| #define TCB_SPAN_CONSTEXPR14 constexpr | ||||
| #else | ||||
| #define TCB_SPAN_CONSTEXPR14 | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR) &&                                  \ | ||||
|     (!defined(_MSC_VER) || _MSC_VER > 1900) | ||||
| #define TCB_SPAN_CONSTEXPR_ASSIGN constexpr | ||||
| #else | ||||
| #define TCB_SPAN_CONSTEXPR_ASSIGN | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TCB_SPAN_NO_CONTRACT_CHECKING) | ||||
| #define TCB_SPAN_CONSTEXPR11 constexpr | ||||
| #else | ||||
| #define TCB_SPAN_CONSTEXPR11 TCB_SPAN_CONSTEXPR14 | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_deduction_guides) | ||||
| #define TCB_SPAN_HAVE_DEDUCTION_GUIDES | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_byte) | ||||
| #define TCB_SPAN_HAVE_STD_BYTE | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_array_constexpr) | ||||
| #define TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC) | ||||
| #define TCB_SPAN_ARRAY_CONSTEXPR constexpr | ||||
| #else | ||||
| #define TCB_SPAN_ARRAY_CONSTEXPR | ||||
| #endif | ||||
| 
 | ||||
| #ifdef TCB_SPAN_HAVE_STD_BYTE | ||||
| using byte = std::byte; | ||||
| #else | ||||
| using byte = unsigned char; | ||||
| #endif | ||||
| 
 | ||||
| #if defined(TCB_SPAN_HAVE_CPP17) | ||||
| #define TCB_SPAN_NODISCARD [[nodiscard]] | ||||
| #else | ||||
| #define TCB_SPAN_NODISCARD | ||||
| #endif | ||||
| 
 | ||||
| TCB_SPAN_INLINE_VAR constexpr std::size_t dynamic_extent = SIZE_MAX; | ||||
| 
 | ||||
| template <typename ElementType, std::size_t Extent = dynamic_extent> | ||||
| class span; | ||||
| 
 | ||||
| namespace detail { | ||||
| 
 | ||||
| template <typename E, std::size_t S> | ||||
| struct span_storage { | ||||
|     constexpr span_storage() noexcept = default; | ||||
| 
 | ||||
|     constexpr span_storage(E* p_ptr, std::size_t /*unused*/) noexcept | ||||
|        : ptr(p_ptr) | ||||
|     {} | ||||
| 
 | ||||
|     E* ptr = nullptr; | ||||
|     static constexpr std::size_t size = S; | ||||
| }; | ||||
| 
 | ||||
| template <typename E> | ||||
| struct span_storage<E, dynamic_extent> { | ||||
|     constexpr span_storage() noexcept = default; | ||||
| 
 | ||||
|     constexpr span_storage(E* p_ptr, std::size_t p_size) noexcept | ||||
|         : ptr(p_ptr), size(p_size) | ||||
|     {} | ||||
| 
 | ||||
|     E* ptr = nullptr; | ||||
|     std::size_t size = 0; | ||||
| }; | ||||
| 
 | ||||
| // Reimplementation of C++17 std::size() and std::data()
 | ||||
| #if defined(TCB_SPAN_HAVE_CPP17) ||                                            \ | ||||
|     defined(__cpp_lib_nonmember_container_access) | ||||
| using std::data; | ||||
| using std::size; | ||||
| #else | ||||
| template <class C> | ||||
| constexpr auto size(const C& c) -> decltype(c.size()) | ||||
| { | ||||
|     return c.size(); | ||||
| } | ||||
| 
 | ||||
| template <class T, std::size_t N> | ||||
| constexpr std::size_t size(const T (&)[N]) noexcept | ||||
| { | ||||
|     return N; | ||||
| } | ||||
| 
 | ||||
| template <class C> | ||||
| constexpr auto data(C& c) -> decltype(c.data()) | ||||
| { | ||||
|     return c.data(); | ||||
| } | ||||
| 
 | ||||
| template <class C> | ||||
| constexpr auto data(const C& c) -> decltype(c.data()) | ||||
| { | ||||
|     return c.data(); | ||||
| } | ||||
| 
 | ||||
| template <class T, std::size_t N> | ||||
| constexpr T* data(T (&array)[N]) noexcept | ||||
| { | ||||
|     return array; | ||||
| } | ||||
| 
 | ||||
| template <class E> | ||||
| constexpr const E* data(std::initializer_list<E> il) noexcept | ||||
| { | ||||
|     return il.begin(); | ||||
| } | ||||
| #endif // TCB_SPAN_HAVE_CPP17
 | ||||
| 
 | ||||
| #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_void_t) | ||||
| using std::void_t; | ||||
| #else | ||||
| template <typename...> | ||||
| using void_t = void; | ||||
| #endif | ||||
| 
 | ||||
| template <typename T> | ||||
| using uncvref_t = | ||||
|     typename std::remove_cv<typename std::remove_reference<T>::type>::type; | ||||
| 
 | ||||
| template <typename> | ||||
| struct is_span : std::false_type {}; | ||||
| 
 | ||||
| template <typename T, std::size_t S> | ||||
| struct is_span<span<T, S>> : std::true_type {}; | ||||
| 
 | ||||
| template <typename> | ||||
| struct is_std_array : std::false_type {}; | ||||
| 
 | ||||
| template <typename T, std::size_t N> | ||||
| struct is_std_array<std::array<T, N>> : std::true_type {}; | ||||
| 
 | ||||
| template <typename, typename = void> | ||||
| struct has_size_and_data : std::false_type {}; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct has_size_and_data<T, void_t<decltype(detail::size(std::declval<T>())), | ||||
|                                    decltype(detail::data(std::declval<T>()))>> | ||||
|     : std::true_type {}; | ||||
| 
 | ||||
| template <typename C, typename U = uncvref_t<C>> | ||||
| struct is_container { | ||||
|     static constexpr bool value = | ||||
|         !is_span<U>::value && !is_std_array<U>::value && | ||||
|         !std::is_array<U>::value && has_size_and_data<C>::value; | ||||
| }; | ||||
| 
 | ||||
| template <typename T> | ||||
| using remove_pointer_t = typename std::remove_pointer<T>::type; | ||||
| 
 | ||||
| template <typename, typename, typename = void> | ||||
| struct is_container_element_type_compatible : std::false_type {}; | ||||
| 
 | ||||
| template <typename T, typename E> | ||||
| struct is_container_element_type_compatible< | ||||
|     T, E, | ||||
|     typename std::enable_if< | ||||
|         !std::is_same< | ||||
|             typename std::remove_cv<decltype(detail::data(std::declval<T>()))>::type, | ||||
|             void>::value && | ||||
|         std::is_convertible< | ||||
|             remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[], | ||||
|             E (*)[]>::value | ||||
|         >::type> | ||||
|     : std::true_type {}; | ||||
| 
 | ||||
| template <typename, typename = size_t> | ||||
| struct is_complete : std::false_type {}; | ||||
| 
 | ||||
| template <typename T> | ||||
| struct is_complete<T, decltype(sizeof(T))> : std::true_type {}; | ||||
| 
 | ||||
| } // namespace detail
 | ||||
| 
 | ||||
| template <typename ElementType, std::size_t Extent> | ||||
| class span { | ||||
|     static_assert(std::is_object<ElementType>::value, | ||||
|                   "A span's ElementType must be an object type (not a " | ||||
|                   "reference type or void)"); | ||||
|     static_assert(detail::is_complete<ElementType>::value, | ||||
|                   "A span's ElementType must be a complete type (not a forward " | ||||
|                   "declaration)"); | ||||
|     static_assert(!std::is_abstract<ElementType>::value, | ||||
|                   "A span's ElementType cannot be an abstract class type"); | ||||
| 
 | ||||
|     using storage_type = detail::span_storage<ElementType, Extent>; | ||||
| 
 | ||||
| public: | ||||
|     // constants and types
 | ||||
|     using element_type = ElementType; | ||||
|     using value_type = typename std::remove_cv<ElementType>::type; | ||||
|     using size_type = std::size_t; | ||||
|     using difference_type = std::ptrdiff_t; | ||||
|     using pointer = element_type*; | ||||
|     using const_pointer = const element_type*; | ||||
|     using reference = element_type&; | ||||
|     using const_reference = const element_type&; | ||||
|     using iterator = pointer; | ||||
|     using reverse_iterator = std::reverse_iterator<iterator>; | ||||
| 
 | ||||
|     static constexpr size_type extent = Extent; | ||||
| 
 | ||||
|     // [span.cons], span constructors, copy, assignment, and destructor
 | ||||
|     template < | ||||
|         std::size_t E = Extent, | ||||
|         typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0> | ||||
|     constexpr span() noexcept | ||||
|     {} | ||||
| 
 | ||||
|     TCB_SPAN_CONSTEXPR11 span(pointer ptr, size_type count) | ||||
|         : storage_(ptr, count) | ||||
|     { | ||||
|         TCB_SPAN_EXPECT(extent == dynamic_extent || count == extent); | ||||
|     } | ||||
| 
 | ||||
|     TCB_SPAN_CONSTEXPR11 span(pointer first_elem, pointer last_elem) | ||||
|         : storage_(first_elem, last_elem - first_elem) | ||||
|     { | ||||
|         TCB_SPAN_EXPECT(extent == dynamic_extent || | ||||
|                         last_elem - first_elem == | ||||
|                             static_cast<std::ptrdiff_t>(extent)); | ||||
|     } | ||||
| 
 | ||||
|     template <std::size_t N, std::size_t E = Extent, | ||||
|               typename std::enable_if< | ||||
|                   (E == dynamic_extent || N == E) && | ||||
|                       detail::is_container_element_type_compatible< | ||||
|                           element_type (&)[N], ElementType>::value, | ||||
|                   int>::type = 0> | ||||
|     constexpr span(element_type (&arr)[N]) noexcept : storage_(arr, N) | ||||
|     {} | ||||
| 
 | ||||
|     template <typename T, std::size_t N, std::size_t E = Extent, | ||||
|               typename std::enable_if< | ||||
|                   (E == dynamic_extent || N == E) && | ||||
|                       detail::is_container_element_type_compatible< | ||||
|                           std::array<T, N>&, ElementType>::value, | ||||
|                   int>::type = 0> | ||||
|     TCB_SPAN_ARRAY_CONSTEXPR span(std::array<T, N>& arr) noexcept | ||||
|         : storage_(arr.data(), N) | ||||
|     {} | ||||
| 
 | ||||
|     template <typename T, std::size_t N, std::size_t E = Extent, | ||||
|               typename std::enable_if< | ||||
|                   (E == dynamic_extent || N == E) && | ||||
|                       detail::is_container_element_type_compatible< | ||||
|                           const std::array<T, N>&, ElementType>::value, | ||||
|                   int>::type = 0> | ||||
|     TCB_SPAN_ARRAY_CONSTEXPR span(const std::array<T, N>& arr) noexcept | ||||
|         : storage_(arr.data(), N) | ||||
|     {} | ||||
| 
 | ||||
|     template < | ||||
|         typename Container, std::size_t E = Extent, | ||||
|         typename std::enable_if< | ||||
|             E == dynamic_extent && detail::is_container<Container>::value && | ||||
|                 detail::is_container_element_type_compatible< | ||||
|                     Container&, ElementType>::value, | ||||
|             int>::type = 0> | ||||
|     constexpr span(Container& cont) | ||||
|         : storage_(detail::data(cont), detail::size(cont)) | ||||
|     {} | ||||
| 
 | ||||
|     template < | ||||
|         typename Container, std::size_t E = Extent, | ||||
|         typename std::enable_if< | ||||
|             E == dynamic_extent && detail::is_container<Container>::value && | ||||
|                 detail::is_container_element_type_compatible< | ||||
|                     const Container&, ElementType>::value, | ||||
|             int>::type = 0> | ||||
|     constexpr span(const Container& cont) | ||||
|         : storage_(detail::data(cont), detail::size(cont)) | ||||
|     {} | ||||
| 
 | ||||
|     constexpr span(const span& other) noexcept = default; | ||||
| 
 | ||||
|     template <typename OtherElementType, std::size_t OtherExtent, | ||||
|               typename std::enable_if< | ||||
|                   (Extent == dynamic_extent || OtherExtent == dynamic_extent || | ||||
|                    Extent == OtherExtent) && | ||||
|                       std::is_convertible<OtherElementType (*)[], | ||||
|                                           ElementType (*)[]>::value, | ||||
|                   int>::type = 0> | ||||
|     constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept | ||||
|         : storage_(other.data(), other.size()) | ||||
|     {} | ||||
| 
 | ||||
|     ~span() noexcept = default; | ||||
| 
 | ||||
|     TCB_SPAN_CONSTEXPR_ASSIGN span& | ||||
|     operator=(const span& other) noexcept = default; | ||||
| 
 | ||||
|     // [span.sub], span subviews
 | ||||
|     template <std::size_t Count> | ||||
|     TCB_SPAN_CONSTEXPR11 span<element_type, Count> first() const | ||||
|     { | ||||
|         TCB_SPAN_EXPECT(Count <= size()); | ||||
|         return {data(), Count}; | ||||
|     } | ||||
| 
 | ||||
|     template <std::size_t Count> | ||||
|     TCB_SPAN_CONSTEXPR11 span<element_type, Count> last() const | ||||
|     { | ||||
|         TCB_SPAN_EXPECT(Count <= size()); | ||||
|         return {data() + (size() - Count), Count}; | ||||
|     } | ||||
| 
 | ||||
|     template <std::size_t Offset, std::size_t Count = dynamic_extent> | ||||
|     using subspan_return_t = | ||||
|         span<ElementType, Count != dynamic_extent | ||||
|                               ? Count | ||||
|                               : (Extent != dynamic_extent ? Extent - Offset | ||||
|                                                           : dynamic_extent)>; | ||||
| 
 | ||||
|     template <std::size_t Offset, std::size_t Count = dynamic_extent> | ||||
|     TCB_SPAN_CONSTEXPR11 subspan_return_t<Offset, Count> subspan() const | ||||
|     { | ||||
|         TCB_SPAN_EXPECT(Offset <= size() && | ||||
|                         (Count == dynamic_extent || Offset + Count <= size())); | ||||
|         return {data() + Offset, | ||||
|                 Count != dynamic_extent ? Count : size() - Offset}; | ||||
|     } | ||||
| 
 | ||||
|     TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent> | ||||
|     first(size_type count) const | ||||
|     { | ||||
|         TCB_SPAN_EXPECT(count <= size()); | ||||
|         return {data(), count}; | ||||
|     } | ||||
| 
 | ||||
|     TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent> | ||||
|     last(size_type count) const | ||||
|     { | ||||
|         TCB_SPAN_EXPECT(count <= size()); | ||||
|         return {data() + (size() - count), count}; | ||||
|     } | ||||
| 
 | ||||
|     TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent> | ||||
|     subspan(size_type offset, size_type count = dynamic_extent) const | ||||
|     { | ||||
|         TCB_SPAN_EXPECT(offset <= size() && | ||||
|                         (count == dynamic_extent || offset + count <= size())); | ||||
|         return {data() + offset, | ||||
|                 count == dynamic_extent ? size() - offset : count}; | ||||
|     } | ||||
| 
 | ||||
|     // [span.obs], span observers
 | ||||
|     constexpr size_type size() const noexcept { return storage_.size; } | ||||
| 
 | ||||
|     constexpr size_type size_bytes() const noexcept | ||||
|     { | ||||
|         return size() * sizeof(element_type); | ||||
|     } | ||||
| 
 | ||||
|     TCB_SPAN_NODISCARD constexpr bool empty() const noexcept | ||||
|     { | ||||
|         return size() == 0; | ||||
|     } | ||||
| 
 | ||||
|     // [span.elem], span element access
 | ||||
|     TCB_SPAN_CONSTEXPR11 reference operator[](size_type idx) const | ||||
|     { | ||||
|         TCB_SPAN_EXPECT(idx < size()); | ||||
|         return *(data() + idx); | ||||
|     } | ||||
| 
 | ||||
|     TCB_SPAN_CONSTEXPR11 reference front() const | ||||
|     { | ||||
|         TCB_SPAN_EXPECT(!empty()); | ||||
|         return *data(); | ||||
|     } | ||||
| 
 | ||||
|     TCB_SPAN_CONSTEXPR11 reference back() const | ||||
|     { | ||||
|         TCB_SPAN_EXPECT(!empty()); | ||||
|         return *(data() + (size() - 1)); | ||||
|     } | ||||
| 
 | ||||
|     constexpr pointer data() const noexcept { return storage_.ptr; } | ||||
| 
 | ||||
|     // [span.iterators], span iterator support
 | ||||
|     constexpr iterator begin() const noexcept { return data(); } | ||||
| 
 | ||||
|     constexpr iterator end() const noexcept { return data() + size(); } | ||||
| 
 | ||||
|     TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin() const noexcept | ||||
|     { | ||||
|         return reverse_iterator(end()); | ||||
|     } | ||||
| 
 | ||||
|     TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rend() const noexcept | ||||
|     { | ||||
|         return reverse_iterator(begin()); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     storage_type storage_{}; | ||||
| }; | ||||
| 
 | ||||
| #ifdef TCB_SPAN_HAVE_DEDUCTION_GUIDES | ||||
| 
 | ||||
| /* Deduction Guides */ | ||||
| template <class T, size_t N> | ||||
| span(T (&)[N])->span<T, N>; | ||||
| 
 | ||||
| template <class T, size_t N> | ||||
| span(std::array<T, N>&)->span<T, N>; | ||||
| 
 | ||||
| template <class T, size_t N> | ||||
| span(const std::array<T, N>&)->span<const T, N>; | ||||
| 
 | ||||
| template <class Container> | ||||
| span(Container&)->span<typename std::remove_reference< | ||||
|     decltype(*detail::data(std::declval<Container&>()))>::type>; | ||||
| 
 | ||||
| template <class Container> | ||||
| span(const Container&)->span<const typename Container::value_type>; | ||||
| 
 | ||||
| #endif // TCB_HAVE_DEDUCTION_GUIDES
 | ||||
| 
 | ||||
| template <typename ElementType, std::size_t Extent> | ||||
| constexpr span<ElementType, Extent> | ||||
| make_span(span<ElementType, Extent> s) noexcept | ||||
| { | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| template <typename T, std::size_t N> | ||||
| constexpr span<T, N> make_span(T (&arr)[N]) noexcept | ||||
| { | ||||
|     return {arr}; | ||||
| } | ||||
| 
 | ||||
| template <typename T, std::size_t N> | ||||
| TCB_SPAN_ARRAY_CONSTEXPR span<T, N> make_span(std::array<T, N>& arr) noexcept | ||||
| { | ||||
|     return {arr}; | ||||
| } | ||||
| 
 | ||||
| template <typename T, std::size_t N> | ||||
| TCB_SPAN_ARRAY_CONSTEXPR span<const T, N> | ||||
| make_span(const std::array<T, N>& arr) noexcept | ||||
| { | ||||
|     return {arr}; | ||||
| } | ||||
| 
 | ||||
| template <typename Container> | ||||
| constexpr span<typename std::remove_reference< | ||||
|     decltype(*detail::data(std::declval<Container&>()))>::type> | ||||
| make_span(Container& cont) | ||||
| { | ||||
|     return {cont}; | ||||
| } | ||||
| 
 | ||||
| template <typename Container> | ||||
| constexpr span<const typename Container::value_type> | ||||
| make_span(const Container& cont) | ||||
| { | ||||
|     return {cont}; | ||||
| } | ||||
| 
 | ||||
| template <typename ElementType, std::size_t Extent> | ||||
| span<const byte, ((Extent == dynamic_extent) ? dynamic_extent | ||||
|                                              : sizeof(ElementType) * Extent)> | ||||
| as_bytes(span<ElementType, Extent> s) noexcept | ||||
| { | ||||
|     return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()}; | ||||
| } | ||||
| 
 | ||||
| template < | ||||
|     class ElementType, size_t Extent, | ||||
|     typename std::enable_if<!std::is_const<ElementType>::value, int>::type = 0> | ||||
| span<byte, ((Extent == dynamic_extent) ? dynamic_extent | ||||
|                                        : sizeof(ElementType) * Extent)> | ||||
| as_writable_bytes(span<ElementType, Extent> s) noexcept | ||||
| { | ||||
|     return {reinterpret_cast<byte*>(s.data()), s.size_bytes()}; | ||||
| } | ||||
| 
 | ||||
| template <std::size_t N, typename E, std::size_t S> | ||||
| constexpr auto get(span<E, S> s) -> decltype(s[N]) | ||||
| { | ||||
|     return s[N]; | ||||
| } | ||||
| 
 | ||||
| } // namespace TCB_SPAN_NAMESPACE_NAME
 | ||||
| 
 | ||||
| namespace std { | ||||
| 
 | ||||
| template <typename ElementType, size_t Extent> | ||||
| class tuple_size<TCB_SPAN_NAMESPACE_NAME::span<ElementType, Extent>> | ||||
|     : public integral_constant<size_t, Extent> {}; | ||||
| 
 | ||||
| template <typename ElementType> | ||||
| class tuple_size<TCB_SPAN_NAMESPACE_NAME::span< | ||||
|     ElementType, TCB_SPAN_NAMESPACE_NAME::dynamic_extent>>; // not defined
 | ||||
| 
 | ||||
| template <size_t I, typename ElementType, size_t Extent> | ||||
| class tuple_element<I, TCB_SPAN_NAMESPACE_NAME::span<ElementType, Extent>> { | ||||
| public: | ||||
|     static_assert(Extent != TCB_SPAN_NAMESPACE_NAME::dynamic_extent && | ||||
|                       I < Extent, | ||||
|                   ""); | ||||
|     using type = ElementType; | ||||
| }; | ||||
| 
 | ||||
| } // end namespace std
 | ||||
| 
 | ||||
| #endif // TCB_SPAN_HPP_INCLUDED
 | ||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Eidolon
						Eidolon