// // span for C++98 and later. // Based on http://wg21.link/p0122r7 // For more information see https://github.com/martinmoene/span-lite // // Copyright 2018-2021 Martin Moene // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef NONSTD_SPAN_HPP_INCLUDED #define NONSTD_SPAN_HPP_INCLUDED #define span_lite_MAJOR 0 #define span_lite_MINOR 10 #define span_lite_PATCH 3 #define span_lite_VERSION span_STRINGIFY(span_lite_MAJOR) "." span_STRINGIFY(span_lite_MINOR) "." span_STRINGIFY(span_lite_PATCH) #define span_STRINGIFY( x ) span_STRINGIFY_( x ) #define span_STRINGIFY_( x ) #x // span configuration: #define span_SPAN_DEFAULT 0 #define span_SPAN_NONSTD 1 #define span_SPAN_STD 2 // tweak header support: #ifdef __has_include # if __has_include() # include # endif #define span_HAVE_TWEAK_HEADER 1 #else #define span_HAVE_TWEAK_HEADER 0 //# pragma message("span.hpp: Note: Tweak header not supported.") #endif // span selection and configuration: #define span_HAVE( feature ) ( span_HAVE_##feature ) #ifndef span_CONFIG_SELECT_SPAN # define span_CONFIG_SELECT_SPAN ( span_HAVE_STD_SPAN ? span_SPAN_STD : span_SPAN_NONSTD ) #endif #ifndef span_CONFIG_EXTENT_TYPE # define span_CONFIG_EXTENT_TYPE std::size_t #endif #ifndef span_CONFIG_SIZE_TYPE # define span_CONFIG_SIZE_TYPE std::size_t #endif #ifdef span_CONFIG_INDEX_TYPE # error `span_CONFIG_INDEX_TYPE` is deprecated since v0.7.0; it is replaced by `span_CONFIG_SIZE_TYPE`. #endif // span configuration (features): #ifndef span_FEATURE_WITH_INITIALIZER_LIST_P2447 # define span_FEATURE_WITH_INITIALIZER_LIST_P2447 0 #endif #ifndef span_FEATURE_WITH_CONTAINER #ifdef span_FEATURE_WITH_CONTAINER_TO_STD # define span_FEATURE_WITH_CONTAINER span_IN_STD( span_FEATURE_WITH_CONTAINER_TO_STD ) #else # define span_FEATURE_WITH_CONTAINER 0 # define span_FEATURE_WITH_CONTAINER_TO_STD 0 #endif #endif #ifndef span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE # define span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE 0 #endif #ifndef span_FEATURE_MEMBER_AT # define span_FEATURE_MEMBER_AT 0 #endif #ifndef span_FEATURE_MEMBER_BACK_FRONT # define span_FEATURE_MEMBER_BACK_FRONT 1 #endif #ifndef span_FEATURE_MEMBER_CALL_OPERATOR # define span_FEATURE_MEMBER_CALL_OPERATOR 0 #endif #ifndef span_FEATURE_MEMBER_SWAP # define span_FEATURE_MEMBER_SWAP 0 #endif #ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB 0 #elif span_FEATURE_NON_MEMBER_FIRST_LAST_SUB # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 1 # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 1 #endif #ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 0 #endif #ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 0 #endif #ifndef span_FEATURE_COMPARISON # define span_FEATURE_COMPARISON 0 // Note: C++20 does not provide comparison #endif #ifndef span_FEATURE_SAME # define span_FEATURE_SAME 0 #endif #if span_FEATURE_SAME && !span_FEATURE_COMPARISON # error `span_FEATURE_SAME` requires `span_FEATURE_COMPARISON` #endif #ifndef span_FEATURE_MAKE_SPAN #ifdef span_FEATURE_MAKE_SPAN_TO_STD # define span_FEATURE_MAKE_SPAN span_IN_STD( span_FEATURE_MAKE_SPAN_TO_STD ) #else # define span_FEATURE_MAKE_SPAN 0 # define span_FEATURE_MAKE_SPAN_TO_STD 0 #endif #endif #ifndef span_FEATURE_BYTE_SPAN # define span_FEATURE_BYTE_SPAN 0 #endif // Control presence of exception handling (try and auto discover): #ifndef span_CONFIG_NO_EXCEPTIONS # if defined(_MSC_VER) # include // for _HAS_EXCEPTIONS # endif # if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) # define span_CONFIG_NO_EXCEPTIONS 0 # else # define span_CONFIG_NO_EXCEPTIONS 1 # undef span_CONFIG_CONTRACT_VIOLATION_THROWS # undef span_CONFIG_CONTRACT_VIOLATION_TERMINATES # define span_CONFIG_CONTRACT_VIOLATION_THROWS 0 # define span_CONFIG_CONTRACT_VIOLATION_TERMINATES 1 # endif #endif // Control pre- and postcondition violation behaviour: #if defined( span_CONFIG_CONTRACT_LEVEL_ON ) # define span_CONFIG_CONTRACT_LEVEL_MASK 0x11 #elif defined( span_CONFIG_CONTRACT_LEVEL_OFF ) # define span_CONFIG_CONTRACT_LEVEL_MASK 0x00 #elif defined( span_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY ) # define span_CONFIG_CONTRACT_LEVEL_MASK 0x01 #elif defined( span_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY ) # define span_CONFIG_CONTRACT_LEVEL_MASK 0x10 #else # define span_CONFIG_CONTRACT_LEVEL_MASK 0x11 #endif #if defined( span_CONFIG_CONTRACT_VIOLATION_THROWS ) # define span_CONFIG_CONTRACT_VIOLATION_THROWS_V span_CONFIG_CONTRACT_VIOLATION_THROWS #else # define span_CONFIG_CONTRACT_VIOLATION_THROWS_V 0 #endif #if defined( span_CONFIG_CONTRACT_VIOLATION_THROWS ) && span_CONFIG_CONTRACT_VIOLATION_THROWS && \ defined( span_CONFIG_CONTRACT_VIOLATION_TERMINATES ) && span_CONFIG_CONTRACT_VIOLATION_TERMINATES # error Please define none or one of span_CONFIG_CONTRACT_VIOLATION_THROWS and span_CONFIG_CONTRACT_VIOLATION_TERMINATES to 1, but not both. #endif // C++ language version detection (C++23 is speculative): // Note: VC14.0/1900 (VS2015) lacks too much from C++14. #ifndef span_CPLUSPLUS # if defined(_MSVC_LANG ) && !defined(__clang__) # define span_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) # else # define span_CPLUSPLUS __cplusplus # endif #endif #define span_CPP98_OR_GREATER ( span_CPLUSPLUS >= 199711L ) #define span_CPP11_OR_GREATER ( span_CPLUSPLUS >= 201103L ) #define span_CPP14_OR_GREATER ( span_CPLUSPLUS >= 201402L ) #define span_CPP17_OR_GREATER ( span_CPLUSPLUS >= 201703L ) #define span_CPP20_OR_GREATER ( span_CPLUSPLUS >= 202002L ) #define span_CPP23_OR_GREATER ( span_CPLUSPLUS >= 202300L ) // C++ language version (represent 98 as 3): #define span_CPLUSPLUS_V ( span_CPLUSPLUS / 100 - (span_CPLUSPLUS > 200000 ? 2000 : 1994) ) #define span_IN_STD( v ) ( ((v) == 98 ? 3 : (v)) >= span_CPLUSPLUS_V ) #define span_CONFIG( feature ) ( span_CONFIG_##feature ) #define span_FEATURE( feature ) ( span_FEATURE_##feature ) #define span_FEATURE_TO_STD( feature ) ( span_IN_STD( span_FEATURE( feature##_TO_STD ) ) ) // Use C++20 std::span if available and requested: #if span_CPP20_OR_GREATER && defined(__has_include ) # if __has_include( ) # define span_HAVE_STD_SPAN 1 # else # define span_HAVE_STD_SPAN 0 # endif #else # define span_HAVE_STD_SPAN 0 #endif #define span_USES_STD_SPAN ( (span_CONFIG_SELECT_SPAN == span_SPAN_STD) || ((span_CONFIG_SELECT_SPAN == span_SPAN_DEFAULT) && span_HAVE_STD_SPAN) ) // // Use C++20 std::span: // #if span_USES_STD_SPAN #include namespace nonstd { using std::span; using std::dynamic_extent; // Note: C++20 does not provide comparison // using std::operator==; // using std::operator!=; // using std::operator<; // using std::operator<=; // using std::operator>; // using std::operator>=; } // namespace nonstd #else // span_USES_STD_SPAN #include // Compiler versions: // // MSVC++ 6.0 _MSC_VER == 1200 span_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0) // MSVC++ 7.0 _MSC_VER == 1300 span_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002) // MSVC++ 7.1 _MSC_VER == 1310 span_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) // MSVC++ 8.0 _MSC_VER == 1400 span_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) // MSVC++ 9.0 _MSC_VER == 1500 span_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008) // MSVC++ 10.0 _MSC_VER == 1600 span_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010) // MSVC++ 11.0 _MSC_VER == 1700 span_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) // MSVC++ 12.0 _MSC_VER == 1800 span_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) // MSVC++ 14.0 _MSC_VER == 1900 span_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) // MSVC++ 14.1 _MSC_VER >= 1910 span_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) // MSVC++ 14.2 _MSC_VER >= 1920 span_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) #if defined(_MSC_VER ) && !defined(__clang__) # define span_COMPILER_MSVC_VER (_MSC_VER ) # define span_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) #else # define span_COMPILER_MSVC_VER 0 # define span_COMPILER_MSVC_VERSION 0 #endif #define span_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) #if defined(__clang__) # define span_COMPILER_CLANG_VERSION span_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) #else # define span_COMPILER_CLANG_VERSION 0 #endif #if defined(__GNUC__) && !defined(__clang__) # define span_COMPILER_GNUC_VERSION span_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #else # define span_COMPILER_GNUC_VERSION 0 #endif // half-open range [lo..hi): #define span_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) // Compiler warning suppression: #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wundef" # pragma clang diagnostic ignored "-Wmismatched-tags" # define span_RESTORE_WARNINGS() _Pragma( "clang diagnostic pop" ) #elif defined __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wundef" # define span_RESTORE_WARNINGS() _Pragma( "GCC diagnostic pop" ) #elif span_COMPILER_MSVC_VER >= 1900 # define span_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes)) # define span_RESTORE_WARNINGS() __pragma(warning(pop )) // Suppress the following MSVC GSL warnings: // - C26439, gsl::f.6 : special function 'function' can be declared 'noexcept' // - C26440, gsl::f.6 : function 'function' can be declared 'noexcept' // - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions; // use brace initialization, gsl::narrow_cast or gsl::narrow // - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead // - C26490: gsl::t.1 : don't use reinterpret_cast span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 ) #else # define span_RESTORE_WARNINGS() /*empty*/ #endif // Presence of language and library features: #ifdef _HAS_CPP0X # define span_HAS_CPP0X _HAS_CPP0X #else # define span_HAS_CPP0X 0 #endif #define span_CPP11_80 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1400) #define span_CPP11_90 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1500) #define span_CPP11_100 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1600) #define span_CPP11_110 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1700) #define span_CPP11_120 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1800) #define span_CPP11_140 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1900) #define span_CPP14_000 (span_CPP14_OR_GREATER) #define span_CPP14_120 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1800) #define span_CPP14_140 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1900) #define span_CPP17_000 (span_CPP17_OR_GREATER) // Presence of C++11 language features: #define span_HAVE_ALIAS_TEMPLATE span_CPP11_140 #define span_HAVE_AUTO span_CPP11_100 #define span_HAVE_CONSTEXPR_11 span_CPP11_140 #define span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG span_CPP11_120 #define span_HAVE_EXPLICIT_CONVERSION span_CPP11_140 #define span_HAVE_INITIALIZER_LIST span_CPP11_120 #define span_HAVE_IS_DEFAULT span_CPP11_140 #define span_HAVE_IS_DELETE span_CPP11_140 #define span_HAVE_NOEXCEPT span_CPP11_140 #define span_HAVE_NULLPTR span_CPP11_100 #define span_HAVE_STATIC_ASSERT span_CPP11_100 // Presence of C++14 language features: #define span_HAVE_CONSTEXPR_14 span_CPP14_000 // Presence of C++17 language features: #define span_HAVE_DEPRECATED span_CPP17_000 #define span_HAVE_NODISCARD span_CPP17_000 #define span_HAVE_NORETURN span_CPP17_000 // MSVC: template parameter deduction guides since Visual Studio 2017 v15.7 #if defined(__cpp_deduction_guides) # define span_HAVE_DEDUCTION_GUIDES 1 #else # define span_HAVE_DEDUCTION_GUIDES (span_CPP17_OR_GREATER && ! span_BETWEEN( span_COMPILER_MSVC_VER, 1, 1913 )) #endif // Presence of C++ library features: #define span_HAVE_ADDRESSOF span_CPP17_000 #define span_HAVE_ARRAY span_CPP11_110 #define span_HAVE_BYTE span_CPP17_000 #define span_HAVE_CONDITIONAL span_CPP11_120 #define span_HAVE_CONTAINER_DATA_METHOD (span_CPP11_140 || ( span_COMPILER_MSVC_VER >= 1500 && span_HAS_CPP0X )) #define span_HAVE_DATA span_CPP17_000 #define span_HAVE_LONGLONG span_CPP11_80 #define span_HAVE_REMOVE_CONST span_CPP11_110 #define span_HAVE_SNPRINTF span_CPP11_140 #define span_HAVE_STRUCT_BINDING span_CPP11_120 #define span_HAVE_TYPE_TRAITS span_CPP11_90 // Presence of byte-lite: #ifdef NONSTD_BYTE_LITE_HPP # define span_HAVE_NONSTD_BYTE 1 #else # define span_HAVE_NONSTD_BYTE 0 #endif // C++ feature usage: #if span_HAVE_ADDRESSOF # define span_ADDRESSOF(x) std::addressof(x) #else # define span_ADDRESSOF(x) (&x) #endif #if span_HAVE_CONSTEXPR_11 # define span_constexpr constexpr #else # define span_constexpr /*span_constexpr*/ #endif #if span_HAVE_CONSTEXPR_14 # define span_constexpr14 constexpr #else # define span_constexpr14 /*span_constexpr*/ #endif #if span_HAVE_EXPLICIT_CONVERSION # define span_explicit explicit #else # define span_explicit /*explicit*/ #endif #if span_HAVE_IS_DELETE # define span_is_delete = delete #else # define span_is_delete #endif #if span_HAVE_IS_DELETE # define span_is_delete_access public #else # define span_is_delete_access private #endif #if span_HAVE_NOEXCEPT && ! span_CONFIG_CONTRACT_VIOLATION_THROWS_V # define span_noexcept noexcept #else # define span_noexcept /*noexcept*/ #endif #if span_HAVE_NULLPTR # define span_nullptr nullptr #else # define span_nullptr NULL #endif #if span_HAVE_DEPRECATED # define span_deprecated(msg) [[deprecated(msg)]] #else # define span_deprecated(msg) /*[[deprecated]]*/ #endif #if span_HAVE_NODISCARD # define span_nodiscard [[nodiscard]] #else # define span_nodiscard /*[[nodiscard]]*/ #endif #if span_HAVE_NORETURN # define span_noreturn [[noreturn]] #else # define span_noreturn /*[[noreturn]]*/ #endif // Other features: #define span_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG #define span_HAVE_ITERATOR_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG // Additional includes: #if span_HAVE( ADDRESSOF ) # include #endif #if span_HAVE( ARRAY ) # include #endif #if span_HAVE( BYTE ) # include #endif #if span_HAVE( DATA ) # include // for std::data(), std::size() #endif #if span_HAVE( TYPE_TRAITS ) # include #endif #if ! span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) # include #endif #if span_FEATURE( MEMBER_AT ) > 1 # include #endif #if ! span_CONFIG( NO_EXCEPTIONS ) # include #endif // Contract violation #define span_ELIDE_CONTRACT_EXPECTS ( 0 == ( span_CONFIG_CONTRACT_LEVEL_MASK & 0x01 ) ) #define span_ELIDE_CONTRACT_ENSURES ( 0 == ( span_CONFIG_CONTRACT_LEVEL_MASK & 0x10 ) ) #if span_ELIDE_CONTRACT_EXPECTS # define span_constexpr_exp span_constexpr # define span_EXPECTS( cond ) /* Expect elided */ #else # define span_constexpr_exp span_constexpr14 # define span_EXPECTS( cond ) span_CONTRACT_CHECK( "Precondition", cond ) #endif #if span_ELIDE_CONTRACT_ENSURES # define span_constexpr_ens span_constexpr # define span_ENSURES( cond ) /* Ensures elided */ #else # define span_constexpr_ens span_constexpr14 # define span_ENSURES( cond ) span_CONTRACT_CHECK( "Postcondition", cond ) #endif #define span_CONTRACT_CHECK( type, cond ) \ cond ? static_cast< void >( 0 ) \ : nonstd::span_lite::detail::report_contract_violation( span_LOCATION( __FILE__, __LINE__ ) ": " type " violation." ) #ifdef __GNUG__ # define span_LOCATION( file, line ) file ":" span_STRINGIFY( line ) #else # define span_LOCATION( file, line ) file "(" span_STRINGIFY( line ) ")" #endif // Method enabling #if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) #define span_REQUIRES_0(VA) \ template< bool B = (VA), typename std::enable_if::type = 0 > # if span_BETWEEN( span_COMPILER_MSVC_VERSION, 1, 140 ) // VS 2013 and earlier seem to have trouble with SFINAE for default non-type arguments # define span_REQUIRES_T(VA) \ , typename = typename std::enable_if< ( VA ), nonstd::span_lite::detail::enabler >::type # else # define span_REQUIRES_T(VA) \ , typename std::enable_if< (VA), int >::type = 0 # endif #define span_REQUIRES_R(R, VA) \ typename std::enable_if< (VA), R>::type #define span_REQUIRES_A(VA) \ , typename std::enable_if< (VA), void*>::type = nullptr #else # define span_REQUIRES_0(VA) /*empty*/ # define span_REQUIRES_T(VA) /*empty*/ # define span_REQUIRES_R(R, VA) R # define span_REQUIRES_A(VA) /*empty*/ #endif namespace nonstd { namespace span_lite { // [views.constants], constants typedef span_CONFIG_EXTENT_TYPE extent_t; typedef span_CONFIG_SIZE_TYPE size_t; span_constexpr const extent_t dynamic_extent = static_cast( -1 ); template< class T, extent_t Extent = dynamic_extent > class span; // Tag to select span constructor taking a container (prevent ms-gsl warning C26426): struct with_container_t { span_constexpr with_container_t() span_noexcept {} }; const span_constexpr with_container_t with_container; // C++11 emulation: namespace std11 { #if span_HAVE( REMOVE_CONST ) using std::remove_cv; using std::remove_const; using std::remove_volatile; #else template< class T > struct remove_const { typedef T type; }; template< class T > struct remove_const< T const > { typedef T type; }; template< class T > struct remove_volatile { typedef T type; }; template< class T > struct remove_volatile< T volatile > { typedef T type; }; template< class T > struct remove_cv { typedef typename std11::remove_volatile< typename std11::remove_const< T >::type >::type type; }; #endif // span_HAVE( REMOVE_CONST ) #if span_HAVE( TYPE_TRAITS ) using std::is_same; using std::is_signed; using std::integral_constant; using std::true_type; using std::false_type; using std::remove_reference; #else template< class T, T v > struct integral_constant { enum { value = v }; }; typedef integral_constant< bool, true > true_type; typedef integral_constant< bool, false > false_type; template< class T, class U > struct is_same : false_type{}; template< class T > struct is_same : true_type{}; template< typename T > struct is_signed : false_type {}; template<> struct is_signed : true_type {}; template<> struct is_signed : true_type {}; template<> struct is_signed : true_type {}; #endif } // namespace std11 // C++17 emulation: namespace std17 { template< bool v > struct bool_constant : std11::integral_constant{}; #if span_CPP11_120 template< class...> using void_t = void; #endif #if span_HAVE( DATA ) using std::data; using std::size; #elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) template< typename T, std::size_t N > inline span_constexpr auto size( const T(&)[N] ) span_noexcept -> size_t { return N; } template< typename C > inline span_constexpr auto size( C const & cont ) -> decltype( cont.size() ) { return cont.size(); } template< typename T, std::size_t N > inline span_constexpr auto data( T(&arr)[N] ) span_noexcept -> T* { return &arr[0]; } template< typename C > inline span_constexpr auto data( C & cont ) -> decltype( cont.data() ) { return cont.data(); } template< typename C > inline span_constexpr auto data( C const & cont ) -> decltype( cont.data() ) { return cont.data(); } template< typename E > inline span_constexpr auto data( std::initializer_list il ) span_noexcept -> E const * { return il.begin(); } #endif // span_HAVE( DATA ) #if span_HAVE( BYTE ) using std::byte; #elif span_HAVE( NONSTD_BYTE ) using nonstd::byte; #endif } // namespace std17 // C++20 emulation: namespace std20 { #if span_HAVE( DEDUCTION_GUIDES ) template< class T > using iter_reference_t = decltype( *std::declval() ); #endif } // namespace std20 // Implementation details: namespace detail { /*enum*/ struct enabler{}; template< typename T > span_constexpr bool is_positive( T x ) { return std11::is_signed::value ? x >= 0 : true; } #if span_HAVE( TYPE_TRAITS ) template< class Q > struct is_span_oracle : std::false_type{}; template< class T, span_CONFIG_EXTENT_TYPE Extent > struct is_span_oracle< span > : std::true_type{}; template< class Q > struct is_span : is_span_oracle< typename std::remove_cv::type >{}; template< class Q > struct is_std_array_oracle : std::false_type{}; #if span_HAVE( ARRAY ) template< class T, std::size_t Extent > struct is_std_array_oracle< std::array > : std::true_type{}; #endif template< class Q > struct is_std_array : is_std_array_oracle< typename std::remove_cv::type >{}; template< class Q > struct is_array : std::false_type {}; template< class T > struct is_array : std::true_type {}; template< class T, std::size_t N > struct is_array : std::true_type {}; #if span_CPP11_140 && ! span_BETWEEN( span_COMPILER_GNUC_VERSION, 1, 500 ) template< class, class = void > struct has_size_and_data : std::false_type{}; template< class C > struct has_size_and_data < C, std17::void_t< decltype( std17::size(std::declval()) ), decltype( std17::data(std::declval()) ) > > : std::true_type{}; template< class, class, class = void > struct is_compatible_element : std::false_type {}; template< class C, class E > struct is_compatible_element < C, E, std17::void_t< decltype( std17::data(std::declval()) ) > > : std::is_convertible< typename std::remove_pointer() ) )>::type(*)[], E(*)[] >{}; template< class C > struct is_container : std17::bool_constant < ! is_span< C >::value && ! is_array< C >::value && ! is_std_array< C >::value && has_size_and_data< C >::value >{}; template< class C, class E > struct is_compatible_container : std17::bool_constant < is_container::value && is_compatible_element::value >{}; #else // span_CPP11_140 template< class C, class E span_REQUIRES_T(( ! is_span< C >::value && ! is_array< C >::value && ! is_std_array< C >::value && ( std::is_convertible< typename std::remove_pointer() ) )>::type(*)[], E(*)[] >::value) // && has_size_and_data< C >::value )) , class = decltype( std17::size(std::declval()) ) , class = decltype( std17::data(std::declval()) ) > struct is_compatible_container : std::true_type{}; #endif // span_CPP11_140 #endif // span_HAVE( TYPE_TRAITS ) #if ! span_CONFIG( NO_EXCEPTIONS ) #if span_FEATURE( MEMBER_AT ) > 1 // format index and size: #if defined(__clang__) # pragma clang diagnostic ignored "-Wlong-long" #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wformat=ll" # pragma GCC diagnostic ignored "-Wlong-long" #endif span_noreturn inline void throw_out_of_range( size_t idx, size_t size ) { const char fmt[] = "span::at(): index '%lli' is out of range [0..%lli)"; char buffer[ 2 * 20 + sizeof fmt ]; sprintf( buffer, fmt, static_cast(idx), static_cast(size) ); throw std::out_of_range( buffer ); } #else // MEMBER_AT span_noreturn inline void throw_out_of_range( size_t /*idx*/, size_t /*size*/ ) { throw std::out_of_range( "span::at(): index outside span" ); } #endif // MEMBER_AT #endif // NO_EXCEPTIONS #if span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) struct contract_violation : std::logic_error { explicit contract_violation( char const * const message ) : std::logic_error( message ) {} }; inline void report_contract_violation( char const * msg ) { throw contract_violation( msg ); } #else // span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) span_noreturn inline void report_contract_violation( char const * /*msg*/ ) span_noexcept { std::terminate(); } #endif // span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) } // namespace detail // Prevent signed-unsigned mismatch: #define span_sizeof(T) static_cast( sizeof(T) ) template< class T > inline span_constexpr size_t to_size( T size ) { return static_cast( size ); } // // [views.span] - A view over a contiguous, single-dimension sequence of objects // template< class T, extent_t Extent /*= dynamic_extent*/ > class span { public: // constants and types typedef T element_type; typedef typename std11::remove_cv< T >::type value_type; typedef T & reference; typedef T * pointer; typedef T const * const_pointer; typedef T const & const_reference; typedef size_t size_type; typedef extent_t extent_type; typedef pointer iterator; typedef const_pointer const_iterator; typedef std::ptrdiff_t difference_type; typedef std::reverse_iterator< iterator > reverse_iterator; typedef std::reverse_iterator< const_iterator > const_reverse_iterator; // static constexpr extent_type extent = Extent; enum { extent = Extent }; // 26.7.3.2 Constructors, copy, and assignment [span.cons] span_REQUIRES_0( ( Extent == 0 ) || ( Extent == dynamic_extent ) ) span_constexpr span() span_noexcept : data_( span_nullptr ) , size_( 0 ) { // span_EXPECTS( data() == span_nullptr ); // span_EXPECTS( size() == 0 ); } #if span_HAVE( ITERATOR_CTOR ) // Didn't yet succeed in combining the next two constructors: span_constexpr_exp span( std::nullptr_t, size_type count ) : data_( span_nullptr ) , size_( count ) { span_EXPECTS( data_ == span_nullptr && count == 0 ); } template< typename It span_REQUIRES_T(( std::is_convertible()), element_type &>::value )) > span_constexpr_exp span( It first, size_type count ) : data_( to_address( first ) ) , size_( count ) { span_EXPECTS( ( data_ == span_nullptr && count == 0 ) || ( data_ != span_nullptr && detail::is_positive( count ) ) ); } #else span_constexpr_exp span( pointer ptr, size_type count ) : data_( ptr ) , size_( count ) { span_EXPECTS( ( ptr == span_nullptr && count == 0 ) || ( ptr != span_nullptr && detail::is_positive( count ) ) ); } #endif #if span_HAVE( ITERATOR_CTOR ) template< typename It, typename End span_REQUIRES_T(( std::is_convertible()), element_type *>::value && ! std::is_convertible::value )) > span_constexpr_exp span( It first, End last ) : data_( to_address( first ) ) , size_( to_size( last - first ) ) { span_EXPECTS( last - first >= 0 ); } #else span_constexpr_exp span( pointer first, pointer last ) : data_( first ) , size_( to_size( last - first ) ) { span_EXPECTS( last - first >= 0 ); } #endif template< std::size_t N span_REQUIRES_T(( (Extent == dynamic_extent || Extent == static_cast(N)) && std::is_convertible< value_type(*)[], element_type(*)[] >::value )) > span_constexpr span( element_type ( &arr )[ N ] ) span_noexcept : data_( span_ADDRESSOF( arr[0] ) ) , size_( N ) {} #if span_HAVE( ARRAY ) template< std::size_t N span_REQUIRES_T(( (Extent == dynamic_extent || Extent == static_cast(N)) && std::is_convertible< value_type(*)[], element_type(*)[] >::value )) > # if span_FEATURE( CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE ) span_constexpr span( std::array< element_type, N > & arr ) span_noexcept # else span_constexpr span( std::array< value_type, N > & arr ) span_noexcept # endif : data_( arr.data() ) , size_( to_size( arr.size() ) ) {} template< std::size_t N # if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) span_REQUIRES_T(( (Extent == dynamic_extent || Extent == static_cast(N)) && std::is_convertible< value_type(*)[], element_type(*)[] >::value )) # endif > span_constexpr span( std::array< value_type, N> const & arr ) span_noexcept : data_( arr.data() ) , size_( to_size( arr.size() ) ) {} #endif // span_HAVE( ARRAY ) #if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) template< class Container span_REQUIRES_T(( detail::is_compatible_container< Container, element_type >::value )) > span_constexpr span( Container & cont ) : data_( std17::data( cont ) ) , size_( to_size( std17::size( cont ) ) ) {} template< class Container span_REQUIRES_T(( std::is_const< element_type >::value && detail::is_compatible_container< Container, element_type >::value )) > span_constexpr span( Container const & cont ) : data_( std17::data( cont ) ) , size_( to_size( std17::size( cont ) ) ) {} #endif // span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) #if span_FEATURE( WITH_CONTAINER ) template< class Container > span_constexpr span( with_container_t, Container & cont ) : data_( cont.size() == 0 ? span_nullptr : span_ADDRESSOF( cont[0] ) ) , size_( to_size( cont.size() ) ) {} template< class Container > span_constexpr span( with_container_t, Container const & cont ) : data_( cont.size() == 0 ? span_nullptr : const_cast( span_ADDRESSOF( cont[0] ) ) ) , size_( to_size( cont.size() ) ) {} #endif #if span_FEATURE( WITH_INITIALIZER_LIST_P2447 ) && span_HAVE( INITIALIZER_LIST ) // constexpr explicit(extent != dynamic_extent) span(std::initializer_list il) noexcept; #if !span_BETWEEN( span_COMPILER_MSVC_VERSION, 120, 130 ) template< extent_t U = Extent span_REQUIRES_T(( U != dynamic_extent )) > #if span_COMPILER_GNUC_VERSION >= 900 // prevent GCC's "-Winit-list-lifetime" span_constexpr14 explicit span( std::initializer_list il ) span_noexcept { data_ = il.begin(); size_ = il.size(); } #else span_constexpr explicit span( std::initializer_list il ) span_noexcept : data_( il.begin() ) , size_( il.size() ) {} #endif #endif // MSVC 120 (VS2013) template< extent_t U = Extent span_REQUIRES_T(( U == dynamic_extent )) > #if span_COMPILER_GNUC_VERSION >= 900 // prevent GCC's "-Winit-list-lifetime" span_constexpr14 /*explicit*/ span( std::initializer_list il ) span_noexcept { data_ = il.begin(); size_ = il.size(); } #else span_constexpr /*explicit*/ span( std::initializer_list il ) span_noexcept : data_( il.begin() ) , size_( il.size() ) {} #endif #endif // P2447 #if span_HAVE( IS_DEFAULT ) span_constexpr span( span const & other ) span_noexcept = default; ~span() span_noexcept = default; span_constexpr14 span & operator=( span const & other ) span_noexcept = default; #else span_constexpr span( span const & other ) span_noexcept : data_( other.data_ ) , size_( other.size_ ) {} ~span() span_noexcept {} span_constexpr14 span & operator=( span const & other ) span_noexcept { data_ = other.data_; size_ = other.size_; return *this; } #endif template< class OtherElementType, extent_type OtherExtent span_REQUIRES_T(( (Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent) && std::is_convertible::value )) > span_constexpr_exp span( span const & other ) span_noexcept : data_( other.data() ) , size_( other.size() ) { span_EXPECTS( OtherExtent == dynamic_extent || other.size() == to_size(OtherExtent) ); } // 26.7.3.3 Subviews [span.sub] template< extent_type Count > span_constexpr_exp span< element_type, Count > first() const { span_EXPECTS( detail::is_positive( Count ) && Count <= size() ); return span< element_type, Count >( data(), Count ); } template< extent_type Count > span_constexpr_exp span< element_type, Count > last() const { span_EXPECTS( detail::is_positive( Count ) && Count <= size() ); return span< element_type, Count >( data() + (size() - Count), Count ); } #if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) template< size_type Offset, extent_type Count = dynamic_extent > #else template< size_type Offset, extent_type Count /*= dynamic_extent*/ > #endif span_constexpr_exp span< element_type, Count > subspan() const { span_EXPECTS( ( detail::is_positive( Offset ) && Offset <= size() ) && ( Count == dynamic_extent || (detail::is_positive( Count ) && Count + Offset <= size()) ) ); return span< element_type, Count >( data() + Offset, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : size() - Offset) ); } span_constexpr_exp span< element_type, dynamic_extent > first( size_type count ) const { span_EXPECTS( detail::is_positive( count ) && count <= size() ); return span< element_type, dynamic_extent >( data(), count ); } span_constexpr_exp span< element_type, dynamic_extent > last( size_type count ) const { span_EXPECTS( detail::is_positive( count ) && count <= size() ); return span< element_type, dynamic_extent >( data() + ( size() - count ), count ); } span_constexpr_exp span< element_type, dynamic_extent > subspan( size_type offset, size_type count = static_cast(dynamic_extent) ) const { span_EXPECTS( ( ( detail::is_positive( offset ) && offset <= size() ) ) && ( count == static_cast(dynamic_extent) || ( detail::is_positive( count ) && offset + count <= size() ) ) ); return span< element_type, dynamic_extent >( data() + offset, count == static_cast(dynamic_extent) ? size() - offset : count ); } // 26.7.3.4 Observers [span.obs] span_constexpr size_type size() const span_noexcept { return size_; } span_constexpr std::ptrdiff_t ssize() const span_noexcept { return static_cast( size_ ); } span_constexpr size_type size_bytes() const span_noexcept { return size() * to_size( sizeof( element_type ) ); } span_nodiscard span_constexpr bool empty() const span_noexcept { return size() == 0; } // 26.7.3.5 Element access [span.elem] span_constexpr_exp reference operator[]( size_type idx ) const { span_EXPECTS( detail::is_positive( idx ) && idx < size() ); return *( data() + idx ); } #if span_FEATURE( MEMBER_CALL_OPERATOR ) span_deprecated("replace operator() with operator[]") span_constexpr_exp reference operator()( size_type idx ) const { span_EXPECTS( detail::is_positive( idx ) && idx < size() ); return *( data() + idx ); } #endif #if span_FEATURE( MEMBER_AT ) span_constexpr14 reference at( size_type idx ) const { #if span_CONFIG( NO_EXCEPTIONS ) return this->operator[]( idx ); #else if ( !detail::is_positive( idx ) || size() <= idx ) { detail::throw_out_of_range( idx, size() ); } return *( data() + idx ); #endif } #endif span_constexpr pointer data() const span_noexcept { return data_; } #if span_FEATURE( MEMBER_BACK_FRONT ) span_constexpr_exp reference front() const span_noexcept { span_EXPECTS( ! empty() ); return *data(); } span_constexpr_exp reference back() const span_noexcept { span_EXPECTS( ! empty() ); return *( data() + size() - 1 ); } #endif // xx.x.x.x Modifiers [span.modifiers] #if span_FEATURE( MEMBER_SWAP ) span_constexpr14 void swap( span & other ) span_noexcept { using std::swap; swap( data_, other.data_ ); swap( size_, other.size_ ); } #endif // 26.7.3.6 Iterator support [span.iterators] span_constexpr iterator begin() const span_noexcept { #if span_CPP11_OR_GREATER return { data() }; #else return iterator( data() ); #endif } span_constexpr iterator end() const span_noexcept { #if span_CPP11_OR_GREATER return { data() + size() }; #else return iterator( data() + size() ); #endif } span_constexpr const_iterator cbegin() const span_noexcept { #if span_CPP11_OR_GREATER return { data() }; #else return const_iterator( data() ); #endif } span_constexpr const_iterator cend() const span_noexcept { #if span_CPP11_OR_GREATER return { data() + size() }; #else return const_iterator( data() + size() ); #endif } span_constexpr reverse_iterator rbegin() const span_noexcept { return reverse_iterator( end() ); } span_constexpr reverse_iterator rend() const span_noexcept { return reverse_iterator( begin() ); } span_constexpr const_reverse_iterator crbegin() const span_noexcept { return const_reverse_iterator ( cend() ); } span_constexpr const_reverse_iterator crend() const span_noexcept { return const_reverse_iterator( cbegin() ); } private: // Note: C++20 has std::pointer_traits::to_address( it ); #if span_HAVE( ITERATOR_CTOR ) static inline span_constexpr pointer to_address( std::nullptr_t ) span_noexcept { return nullptr; } template< typename U > static inline span_constexpr U * to_address( U * p ) span_noexcept { return p; } template< typename Ptr span_REQUIRES_T(( ! std::is_pointer::value )) > static inline span_constexpr pointer to_address( Ptr const & it ) span_noexcept { return to_address( it.operator->() ); } #endif // span_HAVE( ITERATOR_CTOR ) private: pointer data_; size_type size_; }; // class template argument deduction guides: #if span_HAVE( DEDUCTION_GUIDES ) template< class T, size_t N > span( T (&)[N] ) -> span(N)>; template< class T, size_t N > span( std::array & ) -> span(N)>; template< class T, size_t N > span( std::array const & ) -> span(N)>; #if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) template< class Container > span( Container& ) -> span; template< class Container > span( Container const & ) -> span; #endif // iterator: constraints: It satisfies contiguous_­iterator. template< class It, class EndOrSize > span( It, EndOrSize ) -> span< typename std11::remove_reference< typename std20::iter_reference_t >::type >; #endif // span_HAVE( DEDUCTION_GUIDES ) // 26.7.3.7 Comparison operators [span.comparison] #if span_FEATURE( COMPARISON ) #if span_FEATURE( SAME ) template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool same( span const & l, span const & r ) span_noexcept { return std11::is_same::value && l.size() == r.size() && static_cast( l.data() ) == r.data(); } #endif template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator==( span const & l, span const & r ) { return #if span_FEATURE( SAME ) same( l, r ) || #endif ( l.size() == r.size() && std::equal( l.begin(), l.end(), r.begin() ) ); } template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator<( span const & l, span const & r ) { return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() ); } template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator!=( span const & l, span const & r ) { return !( l == r ); } template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator<=( span const & l, span const & r ) { return !( r < l ); } template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator>( span const & l, span const & r ) { return ( r < l ); } template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator>=( span const & l, span const & r ) { return !( l < r ); } #endif // span_FEATURE( COMPARISON ) // 26.7.2.6 views of object representation [span.objectrep] #if span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) // Avoid MSVC 14.1 (1910), VS 2017: warning C4307: '*': integral constant overflow: template< typename T, extent_t Extent > struct BytesExtent { #if span_CPP11_OR_GREATER enum ET : extent_t { value = span_sizeof(T) * Extent }; #else enum ET { value = span_sizeof(T) * Extent }; #endif }; template< typename T > struct BytesExtent< T, dynamic_extent > { #if span_CPP11_OR_GREATER enum ET : extent_t { value = dynamic_extent }; #else enum ET { value = dynamic_extent }; #endif }; template< class T, extent_t Extent > inline span_constexpr span< const std17::byte, BytesExtent::value > as_bytes( span spn ) span_noexcept { #if 0 return { reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() }; #else return span< const std17::byte, BytesExtent::value >( reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() ); // NOLINT #endif } template< class T, extent_t Extent > inline span_constexpr span< std17::byte, BytesExtent::value > as_writable_bytes( span spn ) span_noexcept { #if 0 return { reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() }; #else return span< std17::byte, BytesExtent::value >( reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() ); // NOLINT #endif } #endif // span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) // 27.8 Container and view access [iterator.container] template< class T, extent_t Extent /*= dynamic_extent*/ > span_constexpr std::size_t size( span const & spn ) { return static_cast( spn.size() ); } template< class T, extent_t Extent /*= dynamic_extent*/ > span_constexpr std::ptrdiff_t ssize( span const & spn ) { return static_cast( spn.size() ); } } // namespace span_lite } // namespace nonstd // make available in nonstd: namespace nonstd { using span_lite::dynamic_extent; using span_lite::span; using span_lite::with_container; #if span_FEATURE( COMPARISON ) #if span_FEATURE( SAME ) using span_lite::same; #endif using span_lite::operator==; using span_lite::operator!=; using span_lite::operator<; using span_lite::operator<=; using span_lite::operator>; using span_lite::operator>=; #endif #if span_HAVE( BYTE ) using span_lite::as_bytes; using span_lite::as_writable_bytes; #endif using span_lite::size; using span_lite::ssize; } // namespace nonstd #endif // span_USES_STD_SPAN // make_span() [span-lite extension]: #if span_FEATURE( MAKE_SPAN ) || span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) || span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) #if span_USES_STD_SPAN # define span_constexpr constexpr # define span_noexcept noexcept # define span_nullptr nullptr # ifndef span_CONFIG_EXTENT_TYPE # define span_CONFIG_EXTENT_TYPE std::size_t # endif using extent_t = span_CONFIG_EXTENT_TYPE; #endif // span_USES_STD_SPAN namespace nonstd { namespace span_lite { template< class T > inline span_constexpr span make_span( T * ptr, size_t count ) span_noexcept { return span( ptr, count ); } template< class T > inline span_constexpr span make_span( T * first, T * last ) span_noexcept { return span( first, last ); } template< class T, std::size_t N > inline span_constexpr span(N)> make_span( T ( &arr )[ N ] ) span_noexcept { return span(N)>( &arr[ 0 ], N ); } #if span_USES_STD_SPAN || span_HAVE( ARRAY ) template< class T, std::size_t N > inline span_constexpr span(N)> make_span( std::array< T, N > & arr ) span_noexcept { return span(N)>( arr ); } template< class T, std::size_t N > inline span_constexpr span< const T, static_cast(N) > make_span( std::array< T, N > const & arr ) span_noexcept { return span(N)>( arr ); } #endif // span_HAVE( ARRAY ) #if span_USES_STD_SPAN || span_HAVE( INITIALIZER_LIST ) template< class T > inline span_constexpr span< const T > make_span( std::initializer_list il ) span_noexcept { return span( il.begin(), il.size() ); } #endif // span_HAVE( INITIALIZER_LIST ) #if span_USES_STD_SPAN template< class Container, class EP = decltype( std::data(std::declval())) > inline span_constexpr auto make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer::type > { return span< typename std::remove_pointer::type >( cont ); } template< class Container, class EP = decltype( std::data(std::declval())) > inline span_constexpr auto make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer::type > { return span< const typename std::remove_pointer::type >( cont ); } #elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) && span_HAVE( AUTO ) template< class Container, class EP = decltype( std17::data(std::declval())) > inline span_constexpr auto make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer::type > { return span< typename std::remove_pointer::type >( cont ); } template< class Container, class EP = decltype( std17::data(std::declval())) > inline span_constexpr auto make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer::type > { return span< const typename std::remove_pointer::type >( cont ); } #else template< class T > inline span_constexpr span make_span( span spn ) span_noexcept { return spn; } template< class T, class Allocator > inline span_constexpr span make_span( std::vector & cont ) span_noexcept { return span( with_container, cont ); } template< class T, class Allocator > inline span_constexpr span make_span( std::vector const & cont ) span_noexcept { return span( with_container, cont ); } #endif // span_USES_STD_SPAN || ( ... ) #if ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER ) template< class Container > inline span_constexpr span make_span( with_container_t, Container & cont ) span_noexcept { return span< typename Container::value_type >( with_container, cont ); } template< class Container > inline span_constexpr span make_span( with_container_t, Container const & cont ) span_noexcept { return span< const typename Container::value_type >( with_container, cont ); } #endif // ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER ) // extensions: non-member views: // this feature implies the presence of make_span() #if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) template< extent_t Count, class T, extent_t Extent > span_constexpr span first( span spn ) { return spn.template first(); } template< class T, extent_t Extent > span_constexpr span first( span spn, size_t count ) { return spn.first( count ); } template< extent_t Count, class T, extent_t Extent > span_constexpr span last( span spn ) { return spn.template last(); } template< class T, extent_t Extent > span_constexpr span last( span spn, size_t count ) { return spn.last( count ); } template< size_t Offset, extent_t Count, class T, extent_t Extent > span_constexpr span subspan( span spn ) { return spn.template subspan(); } template< class T, extent_t Extent > span_constexpr span subspan( span spn, size_t offset, extent_t count = dynamic_extent ) { return spn.subspan( offset, count ); } #endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) #if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) && span_CPP11_120 template< extent_t Count, class T > span_constexpr auto first( T & t ) -> decltype( make_span(t).template first() ) { return make_span( t ).template first(); } template< class T > span_constexpr auto first( T & t, size_t count ) -> decltype( make_span(t).first(count) ) { return make_span( t ).first( count ); } template< extent_t Count, class T > span_constexpr auto last( T & t ) -> decltype( make_span(t).template last() ) { return make_span(t).template last(); } template< class T > span_constexpr auto last( T & t, extent_t count ) -> decltype( make_span(t).last(count) ) { return make_span( t ).last( count ); } template< size_t Offset, extent_t Count = dynamic_extent, class T > span_constexpr auto subspan( T & t ) -> decltype( make_span(t).template subspan() ) { return make_span( t ).template subspan(); } template< class T > span_constexpr auto subspan( T & t, size_t offset, extent_t count = dynamic_extent ) -> decltype( make_span(t).subspan(offset, count) ) { return make_span( t ).subspan( offset, count ); } #endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) } // namespace span_lite } // namespace nonstd // make available in nonstd: namespace nonstd { using span_lite::make_span; #if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) || ( span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) && span_CPP11_120 ) using span_lite::first; using span_lite::last; using span_lite::subspan; #endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_[SPAN|CONTAINER] ) } // namespace nonstd #endif // #if span_FEATURE_TO_STD( MAKE_SPAN ) #if span_CPP11_OR_GREATER && span_FEATURE( BYTE_SPAN ) && ( span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) ) namespace nonstd { namespace span_lite { template< class T > inline span_constexpr auto byte_span( T & t ) span_noexcept -> span< std17::byte, span_sizeof(T) > { return span< std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte * >( &t ), span_sizeof(T) ); } template< class T > inline span_constexpr auto byte_span( T const & t ) span_noexcept -> span< const std17::byte, span_sizeof(T) > { return span< const std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte const * >( &t ), span_sizeof(T) ); } } // namespace span_lite } // namespace nonstd // make available in nonstd: namespace nonstd { using span_lite::byte_span; } // namespace nonstd #endif // span_FEATURE( BYTE_SPAN ) #if span_HAVE( STRUCT_BINDING ) #if span_CPP14_OR_GREATER # include #elif span_CPP11_OR_GREATER # include namespace std { template< std::size_t I, typename T > using tuple_element_t = typename tuple_element::type; } #else namespace std { template< typename T > class tuple_size; /*undefined*/ template< std::size_t I, typename T > class tuple_element; /* undefined */ } #endif // span_CPP14_OR_GREATER namespace std { // 26.7.X Tuple interface // std::tuple_size<>: template< typename ElementType, nonstd::span_lite::extent_t Extent > class tuple_size< nonstd::span > : public integral_constant(Extent)> {}; // std::tuple_size<>: Leave undefined for dynamic extent: template< typename ElementType > class tuple_size< nonstd::span >; // std::tuple_element<>: template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent > class tuple_element< I, nonstd::span > { public: #if span_HAVE( STATIC_ASSERT ) static_assert( Extent != nonstd::dynamic_extent && I < Extent, "tuple_element: dynamic extent or index out of range" ); #endif using type = ElementType; }; // std::get<>(), 2 variants: template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent > span_constexpr ElementType & get( nonstd::span & spn ) span_noexcept { #if span_HAVE( STATIC_ASSERT ) static_assert( Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range" ); #endif return spn[I]; } template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent > span_constexpr ElementType const & get( nonstd::span const & spn ) span_noexcept { #if span_HAVE( STATIC_ASSERT ) static_assert( Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range" ); #endif return spn[I]; } } // end namespace std #endif // span_HAVE( STRUCT_BINDING ) #if ! span_USES_STD_SPAN span_RESTORE_WARNINGS() #endif // span_USES_STD_SPAN #endif // NONSTD_SPAN_HPP_INCLUDED