From b157ba9a91ad56f72b728e955dff3f30c1c275b3 Mon Sep 17 00:00:00 2001 From: Martin Moene Date: Wed, 26 Dec 2018 12:22:06 +0100 Subject: [PATCH] Differentiate between extent_t and index_t Add configuration macro span_CONFIG_INDEX_TYPE, still using std::ptrdiff_t --- include/nonstd/span.hpp | 88 +++++++++++++++++++++++------------------ test/span.t.cpp | 33 ++++++++-------- 2 files changed, 66 insertions(+), 55 deletions(-) diff --git a/include/nonstd/span.hpp b/include/nonstd/span.hpp index e64e297..ff18150 100644 --- a/include/nonstd/span.hpp +++ b/include/nonstd/span.hpp @@ -30,6 +30,12 @@ # 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 +#endif + +// span configuration (features): + #ifndef span_FEATURE_WITH_CONTAINER_TO_STD # define span_FEATURE_WITH_CONTAINER_TO_STD 0 #endif @@ -302,7 +308,7 @@ span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 ) #ifdef NONSTD_BYTE_LITE_HPP # define span_HAVE_NONSTD_BYTE 1 -#else +#else # define span_HAVE_NONSTD_BYTE 0 #endif @@ -439,11 +445,13 @@ namespace span_lite { // [views.constants], constants -typedef std::ptrdiff_t index_t; +typedef span_CONFIG_INDEX_TYPE index_t; -span_constexpr const index_t dynamic_extent = -1; +typedef std::ptrdiff_t extent_t; -template< class T, index_t Extent = dynamic_extent > +span_constexpr const extent_t dynamic_extent = -1; + +template< class T, extent_t Extent = dynamic_extent > class span; // Tag to select span constructor taking a container (prevent ms-gsl warning C26426): @@ -591,7 +599,7 @@ span_noreturn inline void report_contract_violation( char const * /*msg*/ ) span // Prevent signed-unsigned mismatch: -#define span_sizeof(T) static_cast( sizeof(T) ) +#define span_sizeof(T) static_cast( sizeof(T) ) template< class T > inline span_constexpr index_t to_size( T size ) @@ -624,7 +632,7 @@ struct can_construct_from : detail::true_type{}; // // [views.span] - A view over a contiguous, single-dimension sequence of objects // -template< class T, index_t Extent /*= dynamic_extent*/ > +template< class T, extent_t Extent /*= dynamic_extent*/ > class span { public: @@ -639,15 +647,17 @@ class span typedef T const & const_reference; typedef index_t index_type; - typedef index_t difference_type; + typedef extent_t extent_type; + + typedef pointer iterator; + typedef const_pointer const_iterator; - 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 index_type extent = Extent; +// static constexpr extent_type extent = Extent; enum { extent = Extent }; // 26.7.3.2 Constructors, copy, and assignment [span.cons] @@ -676,7 +686,7 @@ class span span_constexpr_exp span( pointer firstElem, pointer lastElem ) : data_( firstElem ) - , size_( std::distance( firstElem, lastElem ) ) + , size_( to_size( std::distance( firstElem, lastElem ) ) ) { span_EXPECTS( std::distance( firstElem, lastElem ) >= 0 @@ -793,7 +803,7 @@ class span } #endif - template< class OtherElementType, index_type OtherExtent + template< class OtherElementType, extent_type OtherExtent #if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) , class = typename std::enable_if< (Extent == dynamic_extent || Extent == OtherExtent) && @@ -805,12 +815,12 @@ class span : data_( reinterpret_cast( other.data() ) ) , size_( other.size() ) { - span_EXPECTS( OtherExtent == dynamic_extent || other.size() == OtherExtent ); + span_EXPECTS( OtherExtent == dynamic_extent || other.size() == to_size(OtherExtent) ); } // 26.7.3.3 Subviews [span.sub] - template< index_type Count > + template< extent_type Count > span_constexpr_exp span< element_type, Count > first() const { @@ -819,7 +829,7 @@ class span return span< element_type, Count >( data(), Count ); } - template< index_type Count > + template< extent_type Count > span_constexpr_exp span< element_type, Count > last() const { @@ -829,9 +839,9 @@ class span } #if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG ) - template< index_type Offset, index_type Count = dynamic_extent > + template< index_type Offset, extent_type Count = dynamic_extent > #else - template< index_type Offset, index_type Count /*= dynamic_extent*/ > + template< index_type Offset, extent_type Count /*= dynamic_extent*/ > #endif span_constexpr_exp span< element_type, Count > subspan() const @@ -861,14 +871,14 @@ class span } span_constexpr_exp span< element_type, dynamic_extent > - subspan( index_type offset, index_type count = dynamic_extent ) const + subspan( index_type offset, extent_type count = dynamic_extent ) const { span_EXPECTS( ( ( 0 <= offset && offset <= size() ) ) && - ( count == dynamic_extent || ( 0 <= count && offset + count <= size() ) ) + ( count == dynamic_extent || ( 0 <= count && offset + to_size(count) <= size() ) ) ); - return span< element_type, dynamic_extent >( data() + offset, count == dynamic_extent ? size() - offset : count ); + return span< element_type, dynamic_extent >( data() + offset, count == dynamic_extent ? size() - offset : to_size(count) ); } // 26.7.3.4 Observers [span.obs] @@ -1022,13 +1032,13 @@ class span #if span_HAVE( DEDUCTION_GUIDES ) // span_CPP17_OR_GREATER template< class T, size_t N > -span( T (&)[N] ) -> span; +span( T (&)[N] ) -> span(N)>; template< class T, size_t N > -span( std::array & ) -> span; +span( std::array & ) -> span(N)>; template< class T, size_t N > -span( std::array const & ) -> span; +span( std::array const & ) -> span(N)>; template< class Container > span( Container& ) -> span; @@ -1042,7 +1052,7 @@ span( Container const & ) -> span; #if span_FEATURE( SAME ) -template< class T1, index_t E1, class T2, index_t E2 > +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 detail::is_same::value @@ -1052,7 +1062,7 @@ inline span_constexpr bool same( span const & l, span const & r ) #endif -template< class T1, index_t E1, class T2, index_t E2 > +template< class T1, extent_t E1, class T2, extent_t E2 > inline span_constexpr bool operator==( span const & l, span const & r ) { return @@ -1062,31 +1072,31 @@ inline span_constexpr bool operator==( span const & l, span const ( l.size() == r.size() && std::equal( l.begin(), l.end(), r.begin() ) ); } -template< class T1, index_t E1, class T2, index_t E2 > +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, index_t E1, class T2, index_t E2 > +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, index_t E1, class T2, index_t E2 > +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, index_t E1, class T2, index_t E2 > +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, index_t E1, class T2, index_t E2 > +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 ); @@ -1096,7 +1106,7 @@ inline span_constexpr bool operator>=( span const & l, span const #if span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) -template< class T, index_t Extent > +template< class T, extent_t Extent > inline span_constexpr span< const detail::byte, ( (Extent == dynamic_extent) ? dynamic_extent : (span_sizeof(T) * Extent) ) > as_bytes( span spn ) span_noexcept { @@ -1108,7 +1118,7 @@ as_bytes( span spn ) span_noexcept #endif } -template< class T, index_t Extent > +template< class T, extent_t Extent > inline span_constexpr span< detail::byte, ( (Extent == dynamic_extent) ? dynamic_extent : (span_sizeof(T) * Extent) ) > as_writeable_bytes( span spn ) span_noexcept { @@ -1176,26 +1186,26 @@ make_span( T * first, T * last ) span_noexcept } template< class T, size_t N > -inline span_constexpr span(N)> +inline span_constexpr span(N)> make_span( T ( &arr )[ N ] ) span_noexcept { - return span(N)>( &arr[ 0 ], N ); + return span(N)>( &arr[ 0 ], N ); } #if span_USES_STD_SPAN || span_HAVE( ARRAY ) template< class T, size_t N > -inline span_constexpr span(N)> +inline span_constexpr span(N)> make_span( std::array< T, N > & arr ) span_noexcept { - return span(N)>( arr ); + return span(N)>( arr ); } template< class T, size_t N > -inline span_constexpr span< const T, static_cast(N) > +inline span_constexpr span< const T, static_cast(N) > make_span( std::array< T, N > const & arr ) span_noexcept { - return span(N)>( arr ); + return span(N)>( arr ); } #endif // span_HAVE( ARRAY ) @@ -1268,7 +1278,7 @@ using span_lite::make_span; namespace nonstd { namespace span_lite { - + template< class T > inline span_constexpr auto byte_span( T & t ) span_noexcept -> span< detail::byte, span_sizeof(T) > diff --git a/test/span.t.cpp b/test/span.t.cpp index 51946a6..3c750fa 100644 --- a/test/span.t.cpp +++ b/test/span.t.cpp @@ -5,7 +5,7 @@ // Copyright (c) 2015 Martin Moene // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // -// Distributed under the Boost Software License, Version 1.0. +// 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) #include "span-main.t.hpp" @@ -14,7 +14,8 @@ using namespace nonstd; -typedef span::index_type index_type; +typedef span::index_type index_type; +typedef span::extent_type extent_type; CASE( "span<>: Terminates construction from a nullptr and a non-zero size (C++11)" ) { @@ -109,10 +110,10 @@ CASE( "span<>: Throws on access outside the span via at(): std::out_of_range [s EXPECT_THROWS_AS( v.at(42), std::out_of_range ); EXPECT_THROWS_AS( w.at(42), std::out_of_range ); - - struct F { - static void fail(lest::env & lest_env) { - int arr[] = { 1, 2, 3, }; span v( arr ); EXPECT( (v.at(42), true) ); + + struct F { + static void fail(lest::env & lest_env) { + int arr[] = { 1, 2, 3, }; span v( arr ); EXPECT( (v.at(42), true) ); }}; lest::test fail[] = { lest::test( "F", F::fail ) }; @@ -512,8 +513,8 @@ CASE( "span<>: Allows to create a sub span starting at a given offset with a giv index_type offset = 1; index_type length = 1; - span< int> s = v.subspan( offset, length ); - span t = v.subspan( offset, length ); + span< int> s = v.subspan( offset, extent_type(length) ); + span t = v.subspan( offset, extent_type(length) ); EXPECT( s.size() == length ); EXPECT( t.size() == length ); @@ -725,8 +726,8 @@ CASE( "span<>: Allows to swap with another span [span_FEATURE_MEMBER_SWAP=1]" ) a.swap( b ); - EXPECT( a.size() == 2 ); - EXPECT( b.size() == 3 ); + EXPECT( a.size() == index_type(2) ); + EXPECT( b.size() == index_type(3) ); EXPECT( a[0] == 2 ); EXPECT( b[0] == 1 ); #else @@ -764,7 +765,7 @@ CASE( "span<>: Allows reverse iteration" ) for ( span::reverse_iterator pos = v.rbegin(); pos != v.rend(); ++pos ) { // size_t dist = narrow( std::distance(v.rbegin(), pos) ); - index_type dist = std::distance(v.rbegin(), pos); + index_type dist = static_cast( std::distance(v.rbegin(), pos) ); EXPECT( *pos == arr[ v.size() - 1 - dist ] ); } } @@ -777,7 +778,7 @@ CASE( "span<>: Allows const reverse iteration" ) for ( span::const_reverse_iterator pos = v.crbegin(); pos != v.crend(); ++pos ) { // size_t dist = narrow( std::distance(v.crbegin(), pos) ); - index_type dist = std::distance(v.crbegin(), pos); + index_type dist = static_cast( std::distance(v.crbegin(), pos) ); EXPECT( *pos == arr[ v.size() - 1 - dist ] ); } } @@ -1042,7 +1043,7 @@ CASE( "span<>: Allows to view and change the elements as writable bytes" ) span va( a ); span vb( as_writeable_bytes(va) ); - for ( std::ptrdiff_t i = 0; i < std::ptrdiff_t( sizeof(type) ); ++i ) + for ( index_type i = 0; i < index_type( sizeof(type) ); ++i ) { EXPECT( vb[i] == byte{0} ); } @@ -1050,7 +1051,7 @@ CASE( "span<>: Allows to view and change the elements as writable bytes" ) vb[0] = byte{0x42}; EXPECT( vb[0] == byte{0x42} ); - for ( std::ptrdiff_t i = 1; i < std::ptrdiff_t( sizeof(type) ); ++i ) + for ( index_type i = 1; i < index_type( sizeof(type) ); ++i ) { EXPECT( vb[i] == byte{0} ); } @@ -1272,7 +1273,7 @@ CASE( "byte_span(): Allows building a span of std::byte from a single object (C+ span spn = byte_span( x ); - EXPECT( spn.size() == std::ptrdiff_t( sizeof x ) ); + EXPECT( spn.size() == index_type( sizeof x ) ); #if span_HAVE( NONSTD_BYTE ) EXPECT( spn[0] == to_byte( 0xff ) ); #else @@ -1290,7 +1291,7 @@ CASE( "byte_span(): Allows building a span of const std::byte from a single cons span spn = byte_span( x ); - EXPECT( spn.size() == std::ptrdiff_t( sizeof x ) ); + EXPECT( spn.size() == index_type( sizeof x ) ); #if span_HAVE( NONSTD_BYTE ) EXPECT( spn[0] == to_byte( 0xff ) ); #else