diff --git a/include/ros_msg_parser/utils/span.hpp b/include/ros_msg_parser/utils/span.hpp index 4e329d8..fa6e517 100644 --- a/include/ros_msg_parser/utils/span.hpp +++ b/include/ros_msg_parser/utils/span.hpp @@ -3,7 +3,7 @@ // Based on http://wg21.link/p0122r7 // For more information see https://github.com/martinmoene/span-lite // -// Copyright 2018-2019 Martin Moene +// 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) @@ -12,8 +12,8 @@ #define NONSTD_SPAN_HPP_INCLUDED #define span_lite_MAJOR 0 -#define span_lite_MINOR 5 -#define span_lite_PATCH 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) @@ -26,21 +26,50 @@ #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_INDEX_TYPE -# define span_CONFIG_INDEX_TYPE std::ptrdiff_t +#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 @@ -66,21 +95,37 @@ #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 1 // Note: C++20 does not provide 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 @@ -91,7 +136,10 @@ // Control presence of exception handling (try and auto discover): #ifndef span_CONFIG_NO_EXCEPTIONS -# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND) +# 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 @@ -127,7 +175,7 @@ # 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++20 is speculative): +// C++ language version detection (C++23 is speculative): // Note: VC14.0/1900 (VS2015) lacks too much from C++14. #ifndef span_CPLUSPLUS @@ -142,7 +190,8 @@ #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 >= 202000L ) +#define span_CPP20_OR_GREATER ( span_CPLUSPLUS >= 202002L ) +#define span_CPP23_OR_GREATER ( span_CPLUSPLUS >= 202300L ) // C++ language version (represent 98 as 3): @@ -179,6 +228,7 @@ namespace nonstd { using std::span; +using std::dynamic_extent; // Note: C++20 does not provide comparison // using std::operator==; @@ -195,16 +245,17 @@ using std::span; // Compiler versions: // -// MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0) -// MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002) -// MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003) -// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) -// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) -// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) -// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) -// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) -// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) -// MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017) +// 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 ) @@ -236,6 +287,7 @@ using std::span; #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__ @@ -243,7 +295,7 @@ using std::span; # pragma GCC diagnostic ignored "-Wundef" # define span_RESTORE_WARNINGS() _Pragma( "GCC diagnostic pop" ) -#elif span_COMPILER_MSVC_VERSION >= 140 +#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 )) @@ -264,8 +316,6 @@ span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 ) // Presence of language and library features: -#define span_HAVE( feature ) ( span_HAVE_##feature ) - #ifdef _HAS_CPP0X # define span_HAS_CPP0X _HAS_CPP0X #else @@ -311,7 +361,11 @@ span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 ) // MSVC: template parameter deduction guides since Visual Studio 2017 v15.7 -#define span_HAVE_DEDUCTION_GUIDES (span_CPP17_OR_GREATER && ! span_BETWEEN( span_COMPILER_MSVC_VERSION, 1, 999 )) +#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: @@ -319,11 +373,12 @@ span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 ) #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_VERSION >= 90 && span_HAS_CPP0X )) +#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: @@ -405,6 +460,7 @@ span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 ) // 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: @@ -436,7 +492,7 @@ span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 ) # include #endif -#if span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) +#if ! span_CONFIG( NO_EXCEPTIONS ) # include #endif @@ -473,11 +529,19 @@ span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 ) // Method enabling +#if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) + #define span_REQUIRES_0(VA) \ template< bool B = (VA), typename std::enable_if::type = 0 > -#define span_REQUIRES_T(VA) \ - , typename = typename std::enable_if< (VA), nonstd::span_lite::detail::enabler >::type +# 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 @@ -485,16 +549,24 @@ span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 ) #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_INDEX_TYPE index_t; +typedef span_CONFIG_EXTENT_TYPE extent_t; +typedef span_CONFIG_SIZE_TYPE size_t; -typedef std::ptrdiff_t extent_t; - -span_constexpr const extent_t dynamic_extent = -1; +span_constexpr const extent_t dynamic_extent = static_cast( -1 ); template< class T, extent_t Extent = dynamic_extent > class span; @@ -533,9 +605,11 @@ struct remove_cv #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 @@ -546,6 +620,11 @@ 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 @@ -568,9 +647,9 @@ using void_t = void; using std::data; using std::size; -#elif span_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR +#elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) -template< typename T, size_t N > +template< typename T, std::size_t N > inline span_constexpr auto size( const T(&)[N] ) span_noexcept -> size_t { return N; @@ -582,7 +661,7 @@ inline span_constexpr auto size( C const & cont ) -> decltype( cont.size() ) return cont.size(); } -template< typename T, size_t N > +template< typename T, std::size_t N > inline span_constexpr auto data( T(&arr)[N] ) span_noexcept -> T* { return &arr[0]; @@ -616,18 +695,35 @@ using nonstd::byte; } // 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, std::ptrdiff_t Extent > +template< class T, span_CONFIG_EXTENT_TYPE Extent > struct is_span_oracle< span > : std::true_type{}; template< class Q > @@ -662,37 +758,37 @@ 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{}; +< + 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(*)[] >{}; +< + 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 - >{}; +< + ! 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 - >{}; +< + is_container::value + && is_compatible_element::value +>{}; #else // span_CPP11_140 @@ -703,11 +799,11 @@ template< && ! 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()) ) + // && 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 @@ -726,7 +822,7 @@ struct is_compatible_container : std::true_type{}; # pragma GCC diagnostic ignored "-Wlong-long" #endif -inline void throw_out_of_range( index_t idx, index_t size ) +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 ]; @@ -737,7 +833,7 @@ inline void throw_out_of_range( index_t idx, index_t size ) #else // MEMBER_AT -inline void throw_out_of_range( index_t /*idx*/, index_t /*size*/ ) +span_noreturn inline void throw_out_of_range( size_t /*idx*/, size_t /*size*/ ) { throw std::out_of_range( "span::at(): index outside span" ); } @@ -774,9 +870,9 @@ span_noreturn inline void report_contract_violation( char const * /*msg*/ ) span #define span_sizeof(T) static_cast( sizeof(T) ) template< class T > -inline span_constexpr index_t to_size( T size ) +inline span_constexpr size_t to_size( T size ) { - return static_cast( size ); + return static_cast( size ); } // @@ -796,7 +892,7 @@ class span typedef T const * const_pointer; typedef T const & const_reference; - typedef index_t index_type; + typedef size_t size_type; typedef extent_t extent_type; typedef pointer iterator; @@ -807,15 +903,16 @@ class span typedef std::reverse_iterator< iterator > reverse_iterator; typedef std::reverse_iterator< const_iterator > const_reverse_iterator; - // static constexpr extent_type extent = Extent; +// static constexpr extent_type extent = Extent; enum { extent = Extent }; // 26.7.3.2 Constructors, copy, and assignment [span.cons] -#if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - span_REQUIRES_0(( Extent <= 0 )) -#endif - span_constexpr span() span_noexcept + span_REQUIRES_0( + ( Extent == 0 ) || + ( Extent == dynamic_extent ) + ) + span_constexpr span() span_noexcept : data_( span_nullptr ) , size_( 0 ) { @@ -823,33 +920,74 @@ class span // span_EXPECTS( size() == 0 ); } - span_constexpr_exp span( pointer ptr, index_type count ) +#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 && count >= 0 ) - ); + ( ptr != span_nullptr && detail::is_positive( count ) ) + ); } +#endif - span_constexpr_exp span( pointer firstElem, pointer lastElem ) - : data_( firstElem ) - , size_( to_size( std::distance( firstElem, lastElem ) ) ) +#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( - std::distance( firstElem, lastElem ) >= 0 - ); + last - first >= 0 + ); + } +#else + span_constexpr_exp span( pointer first, pointer last ) + : data_( first ) + , size_( to_size( last - first ) ) + { + span_EXPECTS( + last - first >= 0 + ); } - - template< 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 - > + + 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 ) @@ -857,33 +995,31 @@ class span #if span_HAVE( ARRAY ) - template< 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 - > + 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 + span_constexpr span( std::array< element_type, N > & arr ) span_noexcept # else - span_constexpr span( std::array< value_type, N > & arr ) span_noexcept + span_constexpr span( std::array< value_type, N > & arr ) span_noexcept # endif - : data_( span_ADDRESSOF( arr[0] ) ) + : data_( arr.data() ) , size_( to_size( arr.size() ) ) {} - template< size_t N + 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 - )) + 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_( span_ADDRESSOF( arr[0] ) ) + : data_( arr.data() ) , size_( to_size( arr.size() ) ) {} @@ -891,21 +1027,21 @@ class span #if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) template< class Container - span_REQUIRES_T(( - detail::is_compatible_container< Container, element_type >::value - )) - > + 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_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 ) ) ) @@ -928,6 +1064,52 @@ class span {} #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; @@ -953,15 +1135,13 @@ class span #endif template< class OtherElementType, extent_type OtherExtent -#if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - span_REQUIRES_T(( - (Extent == dynamic_extent || Extent == OtherExtent) - && std::is_convertible::value - )) -#endif - > + 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_( reinterpret_cast( other.data() ) ) + : data_( other.data() ) , size_( other.size() ) { span_EXPECTS( OtherExtent == dynamic_extent || other.size() == to_size(OtherExtent) ); @@ -973,7 +1153,7 @@ class span span_constexpr_exp span< element_type, Count > first() const { - span_EXPECTS( 0 <= Count && Count <= size() ); + span_EXPECTS( detail::is_positive( Count ) && Count <= size() ); return span< element_type, Count >( data(), Count ); } @@ -982,59 +1162,59 @@ class span span_constexpr_exp span< element_type, Count > last() const { - span_EXPECTS( 0 <= Count && Count <= size() ); + 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< index_type Offset, extent_type Count = dynamic_extent > + template< size_type Offset, extent_type Count = dynamic_extent > #else - template< index_type Offset, extent_type Count /*= dynamic_extent*/ > + template< size_type Offset, extent_type Count /*= dynamic_extent*/ > #endif span_constexpr_exp span< element_type, Count > subspan() const { span_EXPECTS( - ( 0 <= Offset && Offset <= size() ) && - ( Count == dynamic_extent || (0 <= Count && Count + Offset <= size()) ) - ); + ( 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( index_type count ) const + first( size_type count ) const { - span_EXPECTS( 0 <= count && count <= size() ); + 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( index_type count ) const + last( size_type count ) const { - span_EXPECTS( 0 <= count && count <= size() ); + 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( index_type offset, index_type count = static_cast(dynamic_extent) ) const + subspan( size_type offset, size_type count = static_cast(dynamic_extent) ) const { span_EXPECTS( - ( ( 0 <= offset && offset <= size() ) ) && - ( count == static_cast(dynamic_extent) || ( 0 <= count && offset + count <= size() ) ) - ); + ( ( 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 ); + data() + offset, count == static_cast(dynamic_extent) ? size() - offset : count ); } // 26.7.3.4 Observers [span.obs] - span_constexpr index_type size() const span_noexcept + span_constexpr size_type size() const span_noexcept { return size_; } @@ -1044,7 +1224,7 @@ class span return static_cast( size_ ); } - span_constexpr index_type size_bytes() const span_noexcept + span_constexpr size_type size_bytes() const span_noexcept { return size() * to_size( sizeof( element_type ) ); } @@ -1056,9 +1236,9 @@ class span // 26.7.3.5 Element access [span.elem] - span_constexpr_exp reference operator[]( index_type idx ) const + span_constexpr_exp reference operator[]( size_type idx ) const { - span_EXPECTS( 0 <= idx && idx < size() ); + span_EXPECTS( detail::is_positive( idx ) && idx < size() ); return *( data() + idx ); } @@ -1066,21 +1246,21 @@ class span #if span_FEATURE( MEMBER_CALL_OPERATOR ) span_deprecated("replace operator() with operator[]") - span_constexpr_exp reference operator()( index_type idx ) const + span_constexpr_exp reference operator()( size_type idx ) const { - span_EXPECTS( 0 <= idx && idx < size() ); + span_EXPECTS( detail::is_positive( idx ) && idx < size() ); return *( data() + idx ); } #endif #if span_FEATURE( MEMBER_AT ) - span_constexpr14 reference at( index_type idx ) const + span_constexpr14 reference at( size_type idx ) const { #if span_CONFIG( NO_EXCEPTIONS ) return this->operator[]( idx ); #else - if ( idx < 0 || size() <= idx ) + if ( !detail::is_positive( idx ) || size() <= idx ) { detail::throw_out_of_range( idx, size() ); } @@ -1183,13 +1363,38 @@ class span } private: - pointer data_; - index_type size_; + + // 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 ) // span_CPP17_OR_GREATER +#if span_HAVE( DEDUCTION_GUIDES ) template< class T, size_t N > span( T (&)[N] ) -> span(N)>; @@ -1200,12 +1405,21 @@ 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] @@ -1217,8 +1431,8 @@ 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(); + && l.size() == r.size() + && static_cast( l.data() ) == r.data(); } #endif @@ -1269,81 +1483,54 @@ inline span_constexpr bool operator>=( span const & l, span const #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, ( (Extent == dynamic_extent) ? dynamic_extent : (span_sizeof(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, ( (Extent == dynamic_extent) ? dynamic_extent : (span_sizeof(T) * Extent) ) >( + 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, ( (Extent == dynamic_extent) ? dynamic_extent : (span_sizeof(T) * Extent) ) > -as_writeable_bytes( span spn ) span_noexcept +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, ( (Extent == dynamic_extent) ? dynamic_extent : (span_sizeof(T) * Extent) ) >( + 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 ) -// extensions: non-member views: -// this feature implies the presence of make_span() - -#if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB ) && 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, index_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< index_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, index_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 ) - // 27.8 Container and view access [iterator.container] template< class T, extent_t Extent /*= dynamic_extent*/ > @@ -1386,7 +1573,7 @@ using span_lite::operator>=; #if span_HAVE( BYTE ) using span_lite::as_bytes; -using span_lite::as_writeable_bytes; +using span_lite::as_writable_bytes; #endif using span_lite::size; @@ -1398,14 +1585,24 @@ using span_lite::ssize; // make_span() [span-lite extension]: -#if span_FEATURE( MAKE_SPAN ) || span_FEATURE( NON_MEMBER_FIRST_LAST_SUB ) +#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, index_t count ) span_noexcept +make_span( T * ptr, size_t count ) span_noexcept { return span( ptr, count ); } @@ -1417,23 +1614,23 @@ make_span( T * first, T * last ) span_noexcept return span( first, last ); } -template< class T, size_t N > +template< class T, std::size_t N > inline span_constexpr span(N)> - make_span( T ( &arr )[ N ] ) span_noexcept +make_span( T ( &arr )[ N ] ) span_noexcept { return span(N)>( &arr[ 0 ], N ); } #if span_USES_STD_SPAN || span_HAVE( ARRAY ) -template< class T, size_t N > +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, size_t N > +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 { @@ -1442,7 +1639,34 @@ make_span( std::array< T, N > const & arr ) span_noexcept #endif // span_HAVE( ARRAY ) -#if span_USES_STD_SPAN || ( span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) && span_HAVE( AUTO ) ) +#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 @@ -1460,6 +1684,13 @@ make_span( Container const & cont ) span_noexcept -> span< const typename std::r #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 @@ -1494,6 +1725,100 @@ make_span( with_container_t, Container const & cont ) span_noexcept #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 @@ -1502,6 +1827,15 @@ make_span( with_container_t, Container const & cont ) span_noexcept 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 ) @@ -1536,6 +1870,76 @@ using span_lite::byte_span; #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