2016-02-24 11:26:28 -08:00
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////
# ifndef GSL_SPAN_H
# define GSL_SPAN_H
2025-02-12 09:16:45 -06:00
# include "./assert" // for Expects
2025-02-14 11:24:51 -06:00
# include "./byte" // for BYTE_TYPE
2025-02-12 09:16:45 -06:00
# include "./span_ext" // for span specialization of gsl::at and other span-related extensions
# include "./util" // for narrow_cast
2017-04-20 07:51:37 -07:00
2022-01-31 22:06:42 +01:00
# include <array> // for array
# include <cstddef> // for ptrdiff_t, size_t, nullptr_t
# include <iterator> // for reverse_iterator, distance, random_access_...
2022-03-22 13:20:54 -07:00
# include <memory> // for pointer_traits
2022-01-31 22:06:42 +01:00
# include <type_traits> // for enable_if_t, declval, is_convertible, inte...
2016-02-24 11:26:28 -08:00
2022-03-22 13:20:54 -07:00
# if defined(__has_include) && __has_include(<version>)
# include <version>
# endif
2019-01-15 10:27:34 -08:00
# if defined(_MSC_VER) && !defined(__clang__)
2017-04-20 07:51:37 -07:00
# pragma warning(push)
2016-02-24 11:26:28 -08:00
2017-04-20 07:51:37 -07:00
// turn off some warnings that are noisy about our Expects statements
# pragma warning(disable : 4127) // conditional expression is constant
2020-02-03 10:56:31 -08:00
# pragma warning( \
disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
2017-07-13 13:53:56 -07:00
# pragma warning(disable : 4702) // unreachable code
2016-03-31 12:01:07 -07:00
2018-08-12 21:44:17 -07:00
// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
2024-01-18 06:25:07 +07:00
# pragma warning(disable : 26495) // uninitialized member when constructor calls constructor
2018-08-12 21:44:17 -07:00
# pragma warning(disable : 26446) // parser bug does not allow attributes on some templates
2016-02-24 11:26:28 -08:00
2018-08-17 11:36:06 -07:00
# endif // _MSC_VER
2018-03-03 19:12:45 -08:00
// See if we have enough C++17 power to use a static constexpr data member
// without needing an out-of-line definition
# if !(defined(__cplusplus) && (__cplusplus >= 201703L))
# define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
# endif // !(defined(__cplusplus) && (__cplusplus >= 201703L))
2024-01-18 06:25:07 +07:00
// GCC 7 does not like the signed unsigned mismatch (size_t ptrdiff_t)
2018-08-12 21:44:17 -07:00
// While there is a conversion from signed to unsigned, it happens at
2020-01-17 14:32:37 +09:00
// compiletime, so the compiler wouldn't have to warn indiscriminately, but
2018-08-12 21:44:17 -07:00
// could check if the source value actually doesn't fit into the target type
2018-06-08 20:41:06 +02:00
// and only warn in those cases.
2019-01-15 10:27:34 -08:00
# if defined(__GNUC__) && __GNUC__ > 6
2018-06-08 20:41:06 +02:00
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wsign-conversion"
# endif
2024-02-26 13:17:12 -08:00
// Turn off clang unsafe buffer warnings as all accessed are guarded by runtime checks
2024-10-12 02:46:21 +02:00
# if defined(__clang__)
# if __has_warning("-Wunsafe-buffer-usage")
2024-02-26 13:17:12 -08:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
2024-10-12 02:46:21 +02:00
# endif // __has_warning("-Wunsafe-buffer-usage")
# endif // defined(__clang__)
2024-02-26 13:17:12 -08:00
2016-02-24 11:26:28 -08:00
namespace gsl
{
2016-06-12 18:28:19 -07:00
// implementation details
2016-03-01 12:11:41 -08:00
namespace details
{
2016-07-20 13:17:47 -07:00
template < class T >
struct is_span_oracle : std : : false_type
2016-05-29 13:52:28 -07:00
{
2016-07-20 13:17:47 -07:00
} ;
2020-02-03 10:56:31 -08:00
template < class ElementType , std : : size_t Extent >
2016-07-20 13:17:47 -07:00
struct is_span_oracle < gsl : : span < ElementType , Extent > > : std : : true_type
{
} ;
template < class T >
2016-07-26 18:34:27 -07:00
struct is_span : public is_span_oracle < std : : remove_cv_t < T > >
{
} ;
template < class T >
struct is_std_array_oracle : std : : false_type
{
} ;
2017-02-13 12:11:45 -08:00
template < class ElementType , std : : size_t Extent >
2016-07-26 18:34:27 -07:00
struct is_std_array_oracle < std : : array < ElementType , Extent > > : std : : true_type
{
} ;
template < class T >
2020-02-14 15:24:46 -08:00
struct is_std_array : is_std_array_oracle < std : : remove_cv_t < T > >
2016-07-20 13:17:47 -07:00
{
} ;
2020-02-03 10:56:31 -08:00
template < std : : size_t From , std : : size_t To >
2016-07-20 13:17:47 -07:00
struct is_allowed_extent_conversion
2020-07-15 13:11:57 -07:00
: std : : integral_constant < bool , From = = To | | To = = dynamic_extent >
2016-07-20 13:17:47 -07:00
{
} ;
template < class From , class To >
struct is_allowed_element_type_conversion
2020-02-14 15:24:46 -08:00
: std : : integral_constant < bool , std : : is_convertible < From ( * ) [ ] , To ( * ) [ ] > : : value >
2016-07-20 13:17:47 -07:00
{
} ;
2020-02-03 18:13:14 -08:00
template < class Type >
2016-08-01 21:41:20 -07:00
class span_iterator
2016-07-20 13:17:47 -07:00
{
public :
2022-03-22 13:20:54 -07:00
# if defined(__cpp_lib_ranges) || (defined(_MSVC_STL_VERSION) && defined(__cpp_lib_concepts))
using iterator_concept = std : : contiguous_iterator_tag ;
# endif // __cpp_lib_ranges
2016-07-20 13:17:47 -07:00
using iterator_category = std : : random_access_iterator_tag ;
2020-02-03 18:13:14 -08:00
using value_type = std : : remove_cv_t < Type > ;
using difference_type = std : : ptrdiff_t ;
using pointer = Type * ;
using reference = Type & ;
2016-07-20 13:17:47 -07:00
2020-02-03 16:26:36 -08:00
# ifdef _MSC_VER
2020-02-03 18:13:14 -08:00
using _Unchecked_type = pointer ;
2023-03-14 13:50:34 -07:00
using _Prevent_inheriting_unwrap = span_iterator ;
2020-02-11 16:36:07 -08:00
# endif // _MSC_VER
2020-02-10 17:09:58 -08:00
constexpr span_iterator ( ) = default ;
constexpr span_iterator ( pointer begin , pointer end , pointer current )
: begin_ ( begin ) , end_ ( end ) , current_ ( current )
2024-11-12 15:41:21 -06:00
{
Expects ( begin_ < = current_ & & current < = end_ ) ;
}
2020-02-10 17:09:58 -08:00
2020-02-03 18:13:14 -08:00
constexpr operator span_iterator < const Type > ( ) const noexcept
2016-07-20 13:17:47 -07:00
{
2020-02-03 16:26:36 -08:00
return { begin_ , end_ , current_ } ;
2016-07-20 13:17:47 -07:00
}
2016-08-01 18:49:48 -07:00
2020-02-03 18:13:14 -08:00
constexpr reference operator * ( ) const noexcept
{
2024-11-12 15:41:21 -06:00
Expects ( current_ ! = end_ ) ;
2020-02-03 18:13:14 -08:00
return * current_ ;
}
2016-07-20 13:17:47 -07:00
2020-02-03 16:26:36 -08:00
constexpr pointer operator - > ( ) const noexcept
{
2024-11-12 15:41:21 -06:00
Expects ( current_ ! = end_ ) ;
2020-02-03 16:26:36 -08:00
return current_ ;
}
2020-01-08 12:34:11 -08:00
constexpr span_iterator & operator + + ( ) noexcept
2016-07-20 13:17:47 -07:00
{
2024-11-12 15:41:21 -06:00
Expects ( current_ ! = end_ ) ;
2020-11-11 22:47:58 +01:00
// clang-format off
GSL_SUPPRESS ( bounds .1 ) // NO-FORMAT: attribute
// clang-format on
2020-02-03 16:26:36 -08:00
+ + current_ ;
2016-07-20 13:17:47 -07:00
return * this ;
}
2020-01-08 12:34:11 -08:00
constexpr span_iterator operator + + ( int ) noexcept
2016-08-01 18:49:48 -07:00
{
2020-02-05 14:36:34 -08:00
span_iterator ret = * this ;
2020-02-03 16:26:36 -08:00
+ + * this ;
2016-08-01 18:49:48 -07:00
return ret ;
}
2016-07-20 13:17:47 -07:00
2020-01-08 12:34:11 -08:00
constexpr span_iterator & operator - - ( ) noexcept
2016-07-20 13:17:47 -07:00
{
2024-11-12 15:41:21 -06:00
Expects ( begin_ ! = current_ ) ;
2020-02-03 16:26:36 -08:00
- - current_ ;
2016-07-20 13:17:47 -07:00
return * this ;
}
2020-01-08 12:34:11 -08:00
constexpr span_iterator operator - - ( int ) noexcept
2016-08-01 18:49:48 -07:00
{
2020-02-05 14:36:34 -08:00
span_iterator ret = * this ;
2020-02-03 16:26:36 -08:00
- - * this ;
2016-08-01 18:49:48 -07:00
return ret ;
}
2016-07-20 13:17:47 -07:00
2020-02-03 16:26:36 -08:00
constexpr span_iterator & operator + = ( const difference_type n ) noexcept
2016-07-20 13:17:47 -07:00
{
2020-02-04 13:30:03 -08:00
if ( n ! = 0 ) Expects ( begin_ & & current_ & & end_ ) ;
2020-02-03 16:26:36 -08:00
if ( n > 0 ) Expects ( end_ - current_ > = n ) ;
2020-02-03 18:12:32 -08:00
if ( n < 0 ) Expects ( current_ - begin_ > = - n ) ;
2020-11-11 22:47:58 +01:00
// clang-format off
GSL_SUPPRESS ( bounds .1 ) // NO-FORMAT: attribute
// clang-format on
2020-02-03 16:26:36 -08:00
current_ + = n ;
return * this ;
}
constexpr span_iterator operator + ( const difference_type n ) const noexcept
{
2020-02-05 14:36:34 -08:00
span_iterator ret = * this ;
2020-02-18 15:36:15 -08:00
ret + = n ;
return ret ;
2016-07-20 13:17:47 -07:00
}
2020-02-03 16:26:36 -08:00
friend constexpr span_iterator operator + ( const difference_type n ,
2020-02-03 18:13:14 -08:00
const span_iterator & rhs ) noexcept
2018-05-09 14:01:22 -07:00
{
return rhs + n ;
}
2020-02-03 16:26:36 -08:00
constexpr span_iterator & operator - = ( const difference_type n ) noexcept
2016-07-20 13:17:47 -07:00
{
2020-02-04 13:30:03 -08:00
if ( n ! = 0 ) Expects ( begin_ & & current_ & & end_ ) ;
2020-02-03 18:31:50 -08:00
if ( n > 0 ) Expects ( current_ - begin_ > = n ) ;
2020-02-03 16:26:36 -08:00
if ( n < 0 ) Expects ( end_ - current_ > = - n ) ;
2023-03-15 00:57:46 +01:00
GSL_SUPPRESS ( bounds .1 )
2020-02-03 16:26:36 -08:00
current_ - = n ;
2016-08-01 18:49:48 -07:00
return * this ;
2016-07-20 13:17:47 -07:00
}
2020-02-03 16:26:36 -08:00
constexpr span_iterator operator - ( const difference_type n ) const noexcept
2016-07-20 13:17:47 -07:00
{
2020-02-05 14:36:34 -08:00
span_iterator ret = * this ;
2020-02-18 15:36:15 -08:00
ret - = n ;
return ret ;
2016-07-20 13:17:47 -07:00
}
2020-02-03 16:26:36 -08:00
template <
2020-02-03 18:13:14 -08:00
class Type2 ,
std : : enable_if_t < std : : is_same < std : : remove_cv_t < Type2 > , value_type > : : value , int > = 0 >
constexpr difference_type operator - ( const span_iterator < Type2 > & rhs ) const noexcept
2016-07-20 13:17:47 -07:00
{
2020-02-03 18:13:14 -08:00
Expects ( begin_ = = rhs . begin_ & & end_ = = rhs . end_ ) ;
2020-02-03 16:26:36 -08:00
return current_ - rhs . current_ ;
2016-07-20 13:17:47 -07:00
}
2020-02-03 16:26:36 -08:00
constexpr reference operator [ ] ( const difference_type n ) const noexcept
2016-07-20 13:17:47 -07:00
{
2020-02-03 16:26:36 -08:00
return * ( * this + n ) ;
2016-07-20 13:17:47 -07:00
}
2020-02-03 16:26:36 -08:00
template <
2020-02-03 18:13:14 -08:00
class Type2 ,
std : : enable_if_t < std : : is_same < std : : remove_cv_t < Type2 > , value_type > : : value , int > = 0 >
constexpr bool operator = = ( const span_iterator < Type2 > & rhs ) const noexcept
2016-07-20 13:17:47 -07:00
{
2020-02-05 12:58:49 -08:00
Expects ( begin_ = = rhs . begin_ & & end_ = = rhs . end_ ) ;
return current_ = = rhs . current_ ;
2016-07-20 13:17:47 -07:00
}
2020-02-03 16:26:36 -08:00
template <
2020-02-03 18:13:14 -08:00
class Type2 ,
std : : enable_if_t < std : : is_same < std : : remove_cv_t < Type2 > , value_type > : : value , int > = 0 >
constexpr bool operator ! = ( const span_iterator < Type2 > & rhs ) const noexcept
2016-07-20 13:17:47 -07:00
{
2020-02-03 16:26:36 -08:00
return ! ( * this = = rhs ) ;
2016-07-20 13:17:47 -07:00
}
2020-02-03 16:26:36 -08:00
template <
2020-02-03 18:13:14 -08:00
class Type2 ,
std : : enable_if_t < std : : is_same < std : : remove_cv_t < Type2 > , value_type > : : value , int > = 0 >
constexpr bool operator < ( const span_iterator < Type2 > & rhs ) const noexcept
2016-07-20 13:17:47 -07:00
{
2020-02-03 18:13:14 -08:00
Expects ( begin_ = = rhs . begin_ & & end_ = = rhs . end_ ) ;
2020-02-03 16:26:36 -08:00
return current_ < rhs . current_ ;
2016-08-08 12:06:47 -07:00
}
2020-02-03 16:26:36 -08:00
template <
2020-02-03 18:13:14 -08:00
class Type2 ,
std : : enable_if_t < std : : is_same < std : : remove_cv_t < Type2 > , value_type > : : value , int > = 0 >
constexpr bool operator > ( const span_iterator < Type2 > & rhs ) const noexcept
2016-08-08 12:06:47 -07:00
{
2020-02-03 18:31:21 -08:00
return rhs < * this ;
2020-02-03 16:26:36 -08:00
}
template <
2020-02-03 18:13:14 -08:00
class Type2 ,
std : : enable_if_t < std : : is_same < std : : remove_cv_t < Type2 > , value_type > : : value , int > = 0 >
constexpr bool operator < = ( const span_iterator < Type2 > & rhs ) const noexcept
2020-02-03 16:26:36 -08:00
{
2020-02-03 18:27:09 -08:00
return ! ( rhs < * this ) ;
2020-02-03 16:26:36 -08:00
}
template <
2020-02-03 18:13:14 -08:00
class Type2 ,
std : : enable_if_t < std : : is_same < std : : remove_cv_t < Type2 > , value_type > : : value , int > = 0 >
constexpr bool operator > = ( const span_iterator < Type2 > & rhs ) const noexcept
2020-02-03 16:26:36 -08:00
{
2020-02-03 18:27:09 -08:00
return ! ( * this < rhs ) ;
2016-07-20 13:17:47 -07:00
}
2018-05-22 18:07:49 -07:00
# ifdef _MSC_VER
// MSVC++ iterator debugging support; allows STL algorithms in 15.8+
// to unwrap span_iterator to a pointer type after a range check in STL
// algorithm calls
2018-08-12 21:44:17 -07:00
friend constexpr void _Verify_range ( span_iterator lhs , span_iterator rhs ) noexcept
{ // test that [lhs, rhs) forms a valid range inside an STL algorithm
2020-02-03 18:13:14 -08:00
Expects ( lhs . begin_ = = rhs . begin_ // range spans have to match
& & lhs . end_ = = rhs . end_ & &
lhs . current_ < = rhs . current_ ) ; // range must not be transposed
2018-05-22 18:07:49 -07:00
}
constexpr void _Verify_offset ( const difference_type n ) const noexcept
2020-02-04 13:30:03 -08:00
{ // test that *this + n is within the range of this call
2020-02-04 15:31:33 -08:00
if ( n ! = 0 ) Expects ( begin_ & & current_ & & end_ ) ;
if ( n > 0 ) Expects ( end_ - current_ > = n ) ;
if ( n < 0 ) Expects ( current_ - begin_ > = - n ) ;
2018-05-22 18:07:49 -07:00
}
2020-02-07 14:09:57 -08:00
// clang-format off
2020-02-03 18:18:14 -08:00
GSL_SUPPRESS ( bounds .1 ) // NO-FORMAT: attribute
2020-02-07 14:09:57 -08:00
// clang-format on
2018-05-22 18:07:49 -07:00
constexpr pointer _Unwrapped ( ) const noexcept
2018-08-12 21:44:17 -07:00
{ // after seeking *this to a high water mark, or using one of the
2018-05-22 18:07:49 -07:00
// _Verify_xxx functions above, unwrap this span_iterator to a raw
// pointer
2020-02-03 16:26:36 -08:00
return current_ ;
2018-05-22 18:07:49 -07:00
}
// Tell the STL that span_iterator should not be unwrapped if it can't
// validate in advance, even in release / optimized builds:
# if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
static constexpr const bool _Unwrap_when_unverified = false ;
# else
static constexpr bool _Unwrap_when_unverified = false ;
# endif
2020-02-07 14:09:57 -08:00
// clang-format off
2020-02-03 18:18:14 -08:00
GSL_SUPPRESS ( con .3 ) // NO-FORMAT: attribute // TODO: false positive
2020-02-07 14:09:57 -08:00
// clang-format on
2018-05-22 18:07:49 -07:00
constexpr void _Seek_to ( const pointer p ) noexcept
2018-08-12 21:44:17 -07:00
{ // adjust the position of *this to previously verified location p
2018-05-22 18:07:49 -07:00
// after _Unwrapped
2020-02-03 16:26:36 -08:00
current_ = p ;
2018-05-22 18:07:49 -07:00
}
# endif
2020-02-03 16:26:36 -08:00
pointer begin_ = nullptr ;
pointer end_ = nullptr ;
pointer current_ = nullptr ;
2016-07-20 13:17:47 -07:00
2022-03-22 13:20:54 -07:00
template < typename Ptr >
friend struct std : : pointer_traits ;
} ;
} } // namespace gsl::details
2022-08-18 21:28:11 +02:00
namespace std
{
2022-03-22 13:20:54 -07:00
template < class Type >
2022-08-18 21:28:11 +02:00
struct pointer_traits < : : gsl : : details : : span_iterator < Type > >
{
using pointer = : : gsl : : details : : span_iterator < Type > ;
using element_type = Type ;
2022-03-22 13:20:54 -07:00
using difference_type = ptrdiff_t ;
2022-08-18 21:28:11 +02:00
static constexpr element_type * to_address ( const pointer i ) noexcept { return i . current_ ; }
2022-03-22 13:20:54 -07:00
} ;
2022-08-18 21:28:11 +02:00
} // namespace std
2022-03-22 13:20:54 -07:00
namespace gsl { namespace details {
2020-02-03 10:56:31 -08:00
template < std : : size_t Ext >
2016-07-26 18:34:27 -07:00
class extent_type
{
public :
2020-02-04 12:01:27 -08:00
using size_type = std : : size_t ;
2016-07-26 18:34:27 -07:00
2020-02-18 14:09:11 -08:00
constexpr extent_type ( ) noexcept = default ;
2016-07-26 18:34:27 -07:00
2020-05-20 16:50:50 -07:00
constexpr explicit extent_type ( extent_type < dynamic_extent > ) ;
2016-07-26 18:34:27 -07:00
2020-05-20 16:50:50 -07:00
constexpr explicit extent_type ( size_type size ) { Expects ( size = = Ext ) ; }
2016-07-26 18:34:27 -07:00
2020-02-04 12:01:27 -08:00
constexpr size_type size ( ) const noexcept { return Ext ; }
2020-03-27 13:14:23 +06:00
private :
# if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
static constexpr const size_type size_ = Ext ; // static size equal to Ext
# else
static constexpr size_type size_ = Ext ; // static size equal to Ext
# endif
2016-07-26 18:34:27 -07:00
} ;
template < >
class extent_type < dynamic_extent >
{
public :
2020-02-04 12:01:27 -08:00
using size_type = std : : size_t ;
2016-07-26 18:34:27 -07:00
2020-02-04 12:01:27 -08:00
template < size_type Other >
2020-05-20 16:50:50 -07:00
constexpr explicit extent_type ( extent_type < Other > ext ) : size_ ( ext . size ( ) )
2018-08-17 11:36:06 -07:00
{ }
2016-07-26 18:34:27 -07:00
2020-05-20 16:50:50 -07:00
constexpr explicit extent_type ( size_type size ) : size_ ( size )
2020-02-03 10:56:31 -08:00
{
Expects ( size ! = dynamic_extent ) ;
}
2016-07-26 18:34:27 -07:00
2020-02-04 12:01:27 -08:00
constexpr size_type size ( ) const noexcept { return size_ ; }
2016-07-26 18:34:27 -07:00
private :
2020-02-04 12:01:27 -08:00
size_type size_ ;
2016-07-26 18:34:27 -07:00
} ;
2018-03-03 19:12:45 -08:00
2020-05-20 13:11:37 -07:00
template < std : : size_t Ext >
constexpr extent_type < Ext > : : extent_type ( extent_type < dynamic_extent > ext )
{
Expects ( ext . size ( ) = = Ext ) ;
}
2020-02-03 10:56:31 -08:00
template < class ElementType , std : : size_t Extent , std : : size_t Offset , std : : size_t Count >
2018-03-03 19:12:45 -08:00
struct calculate_subspan_type
{
2018-08-12 21:44:17 -07:00
using type = span < ElementType , Count ! = dynamic_extent
? Count
: ( Extent ! = dynamic_extent ? Extent - Offset : Extent ) > ;
2018-03-03 19:12:45 -08:00
} ;
2016-03-01 12:11:41 -08:00
} // namespace details
2016-07-20 13:17:47 -07:00
// [span], class template span
2020-02-03 10:56:31 -08:00
template < class ElementType , std : : size_t Extent >
2016-07-20 13:17:47 -07:00
class span
{
2016-02-24 16:11:33 -08:00
public :
2016-07-20 13:17:47 -07:00
// constants and types
2016-02-24 16:11:33 -08:00
using element_type = ElementType ;
2017-04-20 07:51:37 -07:00
using value_type = std : : remove_cv_t < ElementType > ;
2020-02-04 12:01:27 -08:00
using size_type = std : : size_t ;
2016-02-24 16:11:33 -08:00
using pointer = element_type * ;
2020-02-07 14:09:57 -08:00
using const_pointer = const element_type * ;
2016-02-24 16:11:33 -08:00
using reference = element_type & ;
2020-02-07 14:09:57 -08:00
using const_reference = const element_type & ;
2020-02-03 10:56:31 -08:00
using difference_type = std : : ptrdiff_t ;
2016-05-29 13:52:28 -07:00
2020-02-03 16:26:36 -08:00
using iterator = details : : span_iterator < ElementType > ;
2016-02-24 16:11:33 -08:00
using reverse_iterator = std : : reverse_iterator < iterator > ;
2016-05-29 13:52:28 -07:00
2018-03-03 19:12:45 -08:00
# if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
2020-02-04 12:01:27 -08:00
static constexpr const size_type extent { Extent } ;
2018-03-03 19:12:45 -08:00
# else
2020-02-04 12:01:27 -08:00
static constexpr size_type extent { Extent } ;
2018-03-03 19:12:45 -08:00
# endif
2016-02-24 16:11:33 -08:00
2016-07-20 13:17:47 -07:00
// [span.cons], span constructors, copy, assignment, and destructor
2017-01-28 00:08:48 -08:00
template < bool Dependent = false ,
2020-02-07 14:09:57 -08:00
// "Dependent" is needed to make "std::enable_if_t<Dependent || Extent == 0 || Extent
// == dynamic_extent>" SFINAE, since "std::enable_if_t<Extent == 0 || Extent ==
// dynamic_extent>" is ill-formed when Extent is greater than 0.
2020-02-10 13:17:22 -08:00
class = std : : enable_if_t < ( Dependent | |
details : : is_allowed_extent_conversion < 0 , Extent > : : value ) > >
2018-03-15 12:14:29 -07:00
constexpr span ( ) noexcept : storage_ ( nullptr , details : : extent_type < 0 > ( ) )
2018-08-17 11:36:06 -07:00
{ }
2016-02-25 11:42:26 -08:00
2020-07-15 13:11:57 -07:00
template < std : : size_t MyExtent = Extent , std : : enable_if_t < MyExtent ! = dynamic_extent , int > = 0 >
2020-05-20 10:59:57 -07:00
constexpr explicit span ( pointer ptr , size_type count ) noexcept : storage_ ( ptr , count )
2020-02-07 14:09:57 -08:00
{
2020-05-19 16:27:46 -07:00
Expects ( count = = Extent ) ;
2020-02-07 14:09:57 -08:00
}
2016-02-25 11:42:26 -08:00
2020-07-15 13:11:57 -07:00
template < std : : size_t MyExtent = Extent , std : : enable_if_t < MyExtent = = dynamic_extent , int > = 0 >
2020-05-20 10:59:57 -07:00
constexpr span ( pointer ptr , size_type count ) noexcept : storage_ ( ptr , count )
2020-05-19 16:27:46 -07:00
{ }
2020-07-15 13:11:57 -07:00
template < std : : size_t MyExtent = Extent , std : : enable_if_t < MyExtent ! = dynamic_extent , int > = 0 >
2020-05-20 10:59:57 -07:00
constexpr explicit span ( pointer firstElem , pointer lastElem ) noexcept
2020-10-20 00:44:02 +02:00
: storage_ ( firstElem , narrow_cast < std : : size_t > ( lastElem - firstElem ) )
2020-02-07 14:09:57 -08:00
{
2020-05-19 16:27:46 -07:00
Expects ( lastElem - firstElem = = static_cast < difference_type > ( Extent ) ) ;
2020-02-07 14:09:57 -08:00
}
2016-02-29 13:16:48 -08:00
2020-07-15 13:11:57 -07:00
template < std : : size_t MyExtent = Extent , std : : enable_if_t < MyExtent = = dynamic_extent , int > = 0 >
2020-05-19 16:27:46 -07:00
constexpr span ( pointer firstElem , pointer lastElem ) noexcept
2020-10-20 00:44:11 +02:00
: storage_ ( firstElem , narrow_cast < std : : size_t > ( lastElem - firstElem ) )
2020-05-19 16:27:46 -07:00
{ }
2020-02-10 13:17:22 -08:00
template < std : : size_t N ,
std : : enable_if_t < details : : is_allowed_extent_conversion < N , Extent > : : value , int > = 0 >
2018-03-15 12:14:29 -07:00
constexpr span ( element_type ( & arr ) [ N ] ) noexcept
2020-10-29 10:54:37 -07:00
: storage_ ( KnownNotNull { arr } , details : : extent_type < N > ( ) )
2018-08-17 11:36:06 -07:00
{ }
2016-07-26 19:19:47 -07:00
2020-03-17 15:04:58 -07:00
template <
class T , std : : size_t N ,
std : : enable_if_t < ( details : : is_allowed_extent_conversion < N , Extent > : : value & &
details : : is_allowed_element_type_conversion < T , element_type > : : value ) ,
int > = 0 >
2020-03-17 13:53:13 -07:00
constexpr span ( std : : array < T , N > & arr ) noexcept
: storage_ ( KnownNotNull { arr . data ( ) } , details : : extent_type < N > ( ) )
{ }
2020-02-07 14:09:57 -08:00
2020-03-17 13:53:13 -07:00
template < class T , std : : size_t N ,
2020-03-17 15:04:58 -07:00
std : : enable_if_t <
( details : : is_allowed_extent_conversion < N , Extent > : : value & &
details : : is_allowed_element_type_conversion < const T , element_type > : : value ) ,
int > = 0 >
2020-03-17 13:53:13 -07:00
constexpr span ( const std : : array < T , N > & arr ) noexcept
: storage_ ( KnownNotNull { arr . data ( ) } , details : : extent_type < N > ( ) )
{ }
2020-03-17 15:02:00 -07:00
2020-05-20 13:11:37 -07:00
// NB: the SFINAE on these constructors uses .data() as an incomplete/imperfect proxy for the
// requirement on Container to be a contiguous sequence container.
template < std : : size_t MyExtent = Extent , class Container ,
std : : enable_if_t <
2020-10-29 17:38:48 -07:00
MyExtent ! = dynamic_extent & & ! details : : is_span < Container > : : value & &
! details : : is_std_array < Container > : : value & &
std : : is_pointer < decltype ( std : : declval < Container & > ( ) . data ( ) ) > : : value & &
std : : is_convertible <
std : : remove_pointer_t < decltype ( std : : declval < Container & > ( ) . data ( ) ) > ( * ) [ ] ,
element_type ( * ) [ ] > : : value ,
int > = 0 >
2020-05-20 13:11:37 -07:00
constexpr explicit span ( Container & cont ) noexcept : span ( cont . data ( ) , cont . size ( ) )
{ }
template < std : : size_t MyExtent = Extent , class Container ,
std : : enable_if_t <
2020-10-29 17:38:48 -07:00
MyExtent = = dynamic_extent & & ! details : : is_span < Container > : : value & &
! details : : is_std_array < Container > : : value & &
std : : is_pointer < decltype ( std : : declval < Container & > ( ) . data ( ) ) > : : value & &
std : : is_convertible <
std : : remove_pointer_t < decltype ( std : : declval < Container & > ( ) . data ( ) ) > ( * ) [ ] ,
element_type ( * ) [ ] > : : value ,
int > = 0 >
2020-02-05 12:58:49 -08:00
constexpr span ( Container & cont ) noexcept : span ( cont . data ( ) , cont . size ( ) )
2018-08-17 11:36:06 -07:00
{ }
2016-03-01 12:11:41 -08:00
2020-10-29 17:38:48 -07:00
template <
std : : size_t MyExtent = Extent , class Container ,
std : : enable_if_t <
MyExtent ! = dynamic_extent & & std : : is_const < element_type > : : value & &
! details : : is_span < Container > : : value & & ! details : : is_std_array < Container > : : value & &
std : : is_pointer < decltype ( std : : declval < const Container & > ( ) . data ( ) ) > : : value & &
std : : is_convertible <
std : : remove_pointer_t < decltype ( std : : declval < const Container & > ( ) . data ( ) ) > ( * ) [ ] ,
element_type ( * ) [ ] > : : value ,
int > = 0 >
2020-05-20 13:11:37 -07:00
constexpr explicit span ( const Container & cont ) noexcept : span ( cont . data ( ) , cont . size ( ) )
{ }
2020-10-29 17:38:48 -07:00
template <
std : : size_t MyExtent = Extent , class Container ,
std : : enable_if_t <
MyExtent = = dynamic_extent & & std : : is_const < element_type > : : value & &
! details : : is_span < Container > : : value & & ! details : : is_std_array < Container > : : value & &
std : : is_pointer < decltype ( std : : declval < const Container & > ( ) . data ( ) ) > : : value & &
std : : is_convertible <
std : : remove_pointer_t < decltype ( std : : declval < const Container & > ( ) . data ( ) ) > ( * ) [ ] ,
element_type ( * ) [ ] > : : value ,
int > = 0 >
2020-02-07 14:09:57 -08:00
constexpr span ( const Container & cont ) noexcept : span ( cont . data ( ) , cont . size ( ) )
2018-08-17 11:36:06 -07:00
{ }
2016-03-17 17:20:33 -07:00
2018-03-15 12:14:29 -07:00
constexpr span ( const span & other ) noexcept = default ;
2016-03-16 19:39:55 -07:00
2020-10-29 17:38:48 -07:00
template < class OtherElementType , std : : size_t OtherExtent , std : : size_t MyExtent = Extent ,
std : : enable_if_t < ( MyExtent = = dynamic_extent | | MyExtent = = OtherExtent ) & &
details : : is_allowed_element_type_conversion < OtherElementType ,
element_type > : : value ,
int > = 0 >
2020-01-08 11:51:15 -08:00
constexpr span ( const span < OtherElementType , OtherExtent > & other ) noexcept
2016-09-14 22:01:02 -07:00
: storage_ ( other . data ( ) , details : : extent_type < OtherExtent > ( other . size ( ) ) )
2018-08-17 11:36:06 -07:00
{ }
2016-07-20 13:17:47 -07:00
2020-10-29 17:38:48 -07:00
template < class OtherElementType , std : : size_t OtherExtent , std : : size_t MyExtent = Extent ,
std : : enable_if_t < MyExtent ! = dynamic_extent & & OtherExtent = = dynamic_extent & &
details : : is_allowed_element_type_conversion < OtherElementType ,
element_type > : : value ,
int > = 0 >
2020-05-19 16:27:46 -07:00
constexpr explicit span ( const span < OtherElementType , OtherExtent > & other ) noexcept
: storage_ ( other . data ( ) , details : : extent_type < OtherExtent > ( other . size ( ) ) )
{ }
2018-03-15 12:14:29 -07:00
~ span ( ) noexcept = default ;
constexpr span & operator = ( const span & other ) noexcept = default ;
2018-05-09 14:01:22 -07:00
2016-07-20 13:17:47 -07:00
// [span.sub], span subviews
2020-02-03 10:56:31 -08:00
template < std : : size_t Count >
2020-01-08 11:51:15 -08:00
constexpr span < element_type , Count > first ( ) const noexcept
2016-03-18 16:49:29 -07:00
{
2025-01-04 18:50:31 +01:00
static_assert ( Extent = = dynamic_extent | | Count < = Extent ,
" first() cannot extract more elements from a span than it contains. " ) ;
2020-02-03 10:56:31 -08:00
Expects ( Count < = size ( ) ) ;
2020-05-20 13:37:42 -07:00
return span < element_type , Count > { data ( ) , Count } ;
2016-03-18 16:49:29 -07:00
}
2020-02-03 10:56:31 -08:00
template < std : : size_t Count >
2020-02-07 14:09:57 -08:00
// clang-format off
2020-02-03 18:18:14 -08:00
GSL_SUPPRESS ( bounds .1 ) // NO-FORMAT: attribute
2020-03-17 15:04:58 -07:00
// clang-format on
constexpr span < element_type , Count > last ( ) const noexcept
2016-03-18 16:49:29 -07:00
{
2025-01-04 18:50:31 +01:00
static_assert ( Extent = = dynamic_extent | | Count < = Extent ,
" last() cannot extract more elements from a span than it contains. " ) ;
2020-02-18 14:09:11 -08:00
Expects ( Count < = size ( ) ) ;
2020-05-20 13:37:42 -07:00
return span < element_type , Count > { data ( ) + ( size ( ) - Count ) , Count } ;
2016-03-18 16:49:29 -07:00
}
2020-02-03 10:56:31 -08:00
template < std : : size_t Offset , std : : size_t Count = dynamic_extent >
2020-02-07 14:09:57 -08:00
// clang-format off
2020-02-03 18:18:14 -08:00
GSL_SUPPRESS ( bounds .1 ) // NO-FORMAT: attribute
2020-03-17 15:04:58 -07:00
// clang-format on
constexpr auto subspan ( ) const noexcept - >
typename details : : calculate_subspan_type < ElementType , Extent , Offset , Count > : : type
2016-03-18 16:49:29 -07:00
{
2025-01-04 18:50:31 +01:00
static_assert ( Extent = = dynamic_extent | | ( Extent > = Offset & & ( Count = = dynamic_extent | |
Count < = Extent - Offset ) ) ,
" subspan() cannot extract more elements from a span than it contains. " ) ;
2020-02-03 18:13:14 -08:00
Expects ( ( size ( ) > = Offset ) & & ( Count = = dynamic_extent | | ( Count < = size ( ) - Offset ) ) ) ;
2020-10-29 17:38:48 -07:00
using type =
typename details : : calculate_subspan_type < ElementType , Extent , Offset , Count > : : type ;
2020-05-20 16:50:50 -07:00
return type { data ( ) + Offset , Count = = dynamic_extent ? size ( ) - Offset : Count } ;
2016-03-18 16:49:29 -07:00
}
2020-02-04 12:01:27 -08:00
constexpr span < element_type , dynamic_extent > first ( size_type count ) const noexcept
2016-03-18 16:49:29 -07:00
{
2020-02-03 10:56:31 -08:00
Expects ( count < = size ( ) ) ;
2020-05-20 10:59:57 -07:00
return { data ( ) , count } ;
2016-03-18 16:49:29 -07:00
}
2020-02-04 12:01:27 -08:00
constexpr span < element_type , dynamic_extent > last ( size_type count ) const noexcept
2016-03-18 16:49:29 -07:00
{
2020-02-03 10:56:31 -08:00
Expects ( count < = size ( ) ) ;
2017-11-03 16:13:39 -07:00
return make_subspan ( size ( ) - count , dynamic_extent , subspan_selector < Extent > { } ) ;
2016-03-18 16:49:29 -07:00
}
2020-10-29 17:38:48 -07:00
constexpr span < element_type , dynamic_extent >
subspan ( size_type offset , size_type count = dynamic_extent ) const noexcept
2016-03-18 16:49:29 -07:00
{
2017-11-03 16:13:39 -07:00
return make_subspan ( offset , count , subspan_selector < Extent > { } ) ;
2016-03-18 16:49:29 -07:00
}
2016-07-20 13:17:47 -07:00
// [span.obs], span observers
2020-02-04 12:01:27 -08:00
constexpr size_type size ( ) const noexcept { return storage_ . size ( ) ; }
2020-02-05 12:58:49 -08:00
2023-05-09 09:05:26 -07:00
constexpr size_type size_bytes ( ) const noexcept { return size ( ) * sizeof ( element_type ) ; }
2020-02-05 12:58:49 -08:00
2018-03-15 12:14:29 -07:00
constexpr bool empty ( ) const noexcept { return size ( ) = = 0 ; }
2016-02-24 16:11:33 -08:00
2016-07-20 13:17:47 -07:00
// [span.elem], span element access
2020-02-07 14:09:57 -08:00
// clang-format off
2020-02-03 18:18:14 -08:00
GSL_SUPPRESS ( bounds .1 ) // NO-FORMAT: attribute
2020-02-07 14:09:57 -08:00
// clang-format on
2020-02-04 12:01:27 -08:00
constexpr reference operator [ ] ( size_type idx ) const noexcept
2016-02-25 11:42:26 -08:00
{
2020-02-03 18:12:57 -08:00
Expects ( idx < size ( ) ) ;
2016-07-20 09:24:49 -07:00
return data ( ) [ idx ] ;
2016-02-25 11:42:26 -08:00
}
2016-10-26 15:11:24 -06:00
2020-01-09 12:13:12 -08:00
constexpr reference front ( ) const noexcept
2019-11-19 16:03:55 -08:00
{
2020-02-03 13:53:38 -08:00
Expects ( size ( ) > 0 ) ;
2019-11-19 16:03:55 -08:00
return data ( ) [ 0 ] ;
}
2020-01-09 12:13:12 -08:00
constexpr reference back ( ) const noexcept
2019-11-19 16:03:55 -08:00
{
2020-02-03 13:53:38 -08:00
Expects ( size ( ) > 0 ) ;
2019-11-19 16:03:55 -08:00
return data ( ) [ size ( ) - 1 ] ;
}
2020-02-03 10:56:31 -08:00
2018-03-15 12:14:29 -07:00
constexpr pointer data ( ) const noexcept { return storage_ . data ( ) ; }
2016-05-29 13:52:28 -07:00
2016-07-20 13:17:47 -07:00
// [span.iter], span iterator support
2020-02-04 12:01:27 -08:00
constexpr iterator begin ( ) const noexcept
{
const auto data = storage_ . data ( ) ;
2020-04-19 16:41:12 +02:00
// clang-format off
GSL_SUPPRESS ( bounds .1 ) // NO-FORMAT: attribute
// clang-format on
2020-02-04 12:01:27 -08:00
return { data , data + size ( ) , data } ;
}
constexpr iterator end ( ) const noexcept
{
const auto data = storage_ . data ( ) ;
2020-04-19 16:41:12 +02:00
// clang-format off
GSL_SUPPRESS ( bounds .1 ) // NO-FORMAT: attribute
// clang-format on
2020-02-18 14:09:11 -08:00
const auto endData = data + storage_ . size ( ) ;
return { data , endData , endData } ;
2020-02-04 12:01:27 -08:00
}
2018-03-15 12:14:29 -07:00
constexpr reverse_iterator rbegin ( ) const noexcept { return reverse_iterator { end ( ) } ; }
constexpr reverse_iterator rend ( ) const noexcept { return reverse_iterator { begin ( ) } ; }
2016-07-18 11:38:01 -07:00
2018-05-09 14:01:22 -07:00
# ifdef _MSC_VER
// Tell MSVC how to unwrap spans in range-based-for
constexpr pointer _Unchecked_begin ( ) const noexcept { return data ( ) ; }
2018-08-17 11:36:06 -07:00
constexpr pointer _Unchecked_end ( ) const noexcept
2018-08-12 21:44:17 -07:00
{
2020-02-07 14:09:57 -08:00
// clang-format off
2020-02-03 18:18:14 -08:00
GSL_SUPPRESS ( bounds .1 ) // NO-FORMAT: attribute
2020-02-07 14:09:57 -08:00
// clang-format on
2018-08-12 21:44:17 -07:00
return data ( ) + size ( ) ;
}
2018-05-09 14:01:22 -07:00
# endif // _MSC_VER
2016-02-24 16:11:33 -08:00
private :
2018-03-15 12:14:29 -07:00
// Needed to remove unnecessary null check in subspans
2018-05-09 14:01:22 -07:00
struct KnownNotNull
2018-03-15 12:14:29 -07:00
{
pointer p ;
} ;
2016-07-20 13:17:47 -07:00
// this implementation detail class lets us take advantage of the
2016-02-28 00:50:53 -08:00
// empty base class optimization to pay for only storage of a single
// pointer in the case of fixed-size spans
template < class ExtentType >
class storage_type : public ExtentType
{
public :
2018-05-09 14:01:22 -07:00
// KnownNotNull parameter is needed to remove unnecessary null check
2018-03-15 12:14:29 -07:00
// in subspans and constructors from arrays
2016-02-28 00:50:53 -08:00
template < class OtherExtentType >
2018-08-12 21:44:17 -07:00
constexpr storage_type ( KnownNotNull data , OtherExtentType ext )
: ExtentType ( ext ) , data_ ( data . p )
2022-04-28 14:58:25 -07:00
{ }
2016-02-28 00:50:53 -08:00
2018-03-15 12:14:29 -07:00
template < class OtherExtentType >
constexpr storage_type ( pointer data , OtherExtentType ext ) : ExtentType ( ext ) , data_ ( data )
{
2018-08-12 21:44:17 -07:00
Expects ( data | | ExtentType : : size ( ) = = 0 ) ;
2018-03-15 12:14:29 -07:00
}
constexpr pointer data ( ) const noexcept { return data_ ; }
2016-02-28 00:50:53 -08:00
private :
pointer data_ ;
} ;
2016-07-26 18:34:27 -07:00
storage_type < details : : extent_type < Extent > > storage_ ;
2017-11-03 16:13:39 -07:00
2018-03-15 12:14:29 -07:00
// The rest is needed to remove unnecessary null check
// in subspans and constructors from arrays
2020-02-14 15:24:46 -08:00
constexpr span ( KnownNotNull ptr , size_type count ) noexcept : storage_ ( ptr , count ) { }
2017-11-03 16:13:39 -07:00
2020-02-03 10:56:31 -08:00
template < std : : size_t CallerExtent >
2018-08-12 21:44:17 -07:00
class subspan_selector
{
} ;
2017-11-03 16:13:39 -07:00
2020-02-03 10:56:31 -08:00
template < std : : size_t CallerExtent >
2020-10-29 17:38:48 -07:00
constexpr span < element_type , dynamic_extent >
make_subspan ( size_type offset , size_type count , subspan_selector < CallerExtent > ) const noexcept
2017-11-03 16:13:39 -07:00
{
2018-08-12 21:44:17 -07:00
const span < element_type , dynamic_extent > tmp ( * this ) ;
2017-11-03 16:13:39 -07:00
return tmp . subspan ( offset , count ) ;
}
2020-02-07 14:09:57 -08:00
// clang-format off
2020-02-03 18:18:14 -08:00
GSL_SUPPRESS ( bounds .1 ) // NO-FORMAT: attribute
2020-02-07 14:09:57 -08:00
// clang-format on
2020-02-10 13:17:22 -08:00
constexpr span < element_type , dynamic_extent >
2020-02-14 15:24:46 -08:00
make_subspan ( size_type offset , size_type count , subspan_selector < dynamic_extent > ) const noexcept
2017-11-03 16:13:39 -07:00
{
2020-02-03 16:26:36 -08:00
Expects ( size ( ) > = offset ) ;
2018-08-12 21:44:17 -07:00
if ( count = = dynamic_extent ) { return { KnownNotNull { data ( ) + offset } , size ( ) - offset } ; }
2017-11-03 16:13:39 -07:00
2020-02-03 10:56:31 -08:00
Expects ( size ( ) - offset > = count ) ;
2018-08-12 21:44:17 -07:00
return { KnownNotNull { data ( ) + offset } , count } ;
2017-11-03 16:13:39 -07:00
}
2016-02-24 16:11:33 -08:00
} ;
2020-02-07 14:09:57 -08:00
# if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
// Deduction Guides
template < class Type , std : : size_t Extent >
2020-10-29 17:38:48 -07:00
span ( Type ( & ) [ Extent ] ) - > span < Type , Extent > ;
2020-02-07 14:09:57 -08:00
template < class Type , std : : size_t Size >
2020-10-29 17:38:48 -07:00
span ( std : : array < Type , Size > & ) - > span < Type , Size > ;
2020-02-07 14:09:57 -08:00
template < class Type , std : : size_t Size >
2020-10-29 17:38:48 -07:00
span ( const std : : array < Type , Size > & ) - > span < const Type , Size > ;
2020-02-07 14:09:57 -08:00
2020-05-28 18:00:40 -07:00
template < class Container ,
2020-10-29 17:38:48 -07:00
class Element = std : : remove_pointer_t < decltype ( std : : declval < Container & > ( ) . data ( ) ) > >
span ( Container & ) - > span < Element > ;
2020-05-28 14:04:31 -07:00
2020-05-28 18:00:40 -07:00
template < class Container ,
2020-10-29 17:38:48 -07:00
class Element = std : : remove_pointer_t < decltype ( std : : declval < const Container & > ( ) . data ( ) ) > >
span ( const Container & ) - > span < Element > ;
2020-05-28 14:04:31 -07:00
2020-02-07 14:09:57 -08:00
# endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) )
2018-03-03 19:12:45 -08:00
# if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
2023-09-11 10:06:40 -07:00
# if defined(__clang__) && defined(_MSC_VER) && defined(__cplusplus) && (__cplusplus < 201703L)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated" // Bug in clang-cl.exe which raises a C++17 -Wdeprecated warning about this static constexpr workaround in C++14 mode.
# endif // defined(__clang__) && defined(_MSC_VER) && defined(__cplusplus) && (__cplusplus < 201703L)
2020-02-03 10:56:31 -08:00
template < class ElementType , std : : size_t Extent >
2020-02-04 12:01:27 -08:00
constexpr const typename span < ElementType , Extent > : : size_type span < ElementType , Extent > : : extent ;
2023-09-11 10:06:40 -07:00
# if defined(__clang__) && defined(_MSC_VER) && defined(__cplusplus) && (__cplusplus < 201703L)
# pragma clang diagnostic pop
# endif // defined(__clang__) && defined(_MSC_VER) && defined(__cplusplus) && (__cplusplus < 201703L)
2018-03-03 19:12:45 -08:00
# endif
2016-05-29 17:06:29 -07:00
namespace details
{
// if we only supported compilers with good constexpr support then
// this pair of classes could collapse down to a constexpr function
2017-02-13 12:11:45 -08:00
// we should use a narrow_cast<> to go to std::size_t, but older compilers may not see it as
2016-07-20 13:17:47 -07:00
// constexpr
2016-05-29 17:06:29 -07:00
// and so will fail compilation of the template
2020-02-03 10:56:31 -08:00
template < class ElementType , std : : size_t Extent >
struct calculate_byte_size : std : : integral_constant < std : : size_t , sizeof ( ElementType ) * Extent >
2016-07-20 13:17:47 -07:00
{
2020-02-18 14:09:11 -08:00
static_assert ( Extent < dynamic_extent / sizeof ( ElementType ) , " Size is too big. " ) ;
2016-07-20 13:17:47 -07:00
} ;
2016-05-29 17:06:29 -07:00
template < class ElementType >
2016-07-20 13:17:47 -07:00
struct calculate_byte_size < ElementType , dynamic_extent >
2020-02-03 10:56:31 -08:00
: std : : integral_constant < std : : size_t , dynamic_extent >
2016-07-20 13:17:47 -07:00
{
} ;
2018-08-12 21:44:17 -07:00
} // namespace details
2016-05-29 17:06:29 -07:00
2016-07-20 13:17:47 -07:00
// [span.objectrep], views of object representation
2020-02-03 10:56:31 -08:00
template < class ElementType , std : : size_t Extent >
2025-02-14 11:24:51 -06:00
span < const BYTE_TYPE , details : : calculate_byte_size < ElementType , Extent > : : value >
2018-03-15 12:14:29 -07:00
as_bytes ( span < ElementType , Extent > s ) noexcept
2016-07-20 13:17:47 -07:00
{
2025-02-14 11:24:51 -06:00
using type = span < const BYTE_TYPE , details : : calculate_byte_size < ElementType , Extent > : : value > ;
2020-05-20 17:52:03 -07:00
2020-02-07 14:09:57 -08:00
// clang-format off
2020-02-03 18:18:14 -08:00
GSL_SUPPRESS ( type .1 ) // NO-FORMAT: attribute
2020-02-07 14:09:57 -08:00
// clang-format on
2025-02-14 11:24:51 -06:00
return type { reinterpret_cast < const BYTE_TYPE * > ( s . data ( ) ) , s . size_bytes ( ) } ;
2016-07-20 13:17:47 -07:00
}
2016-02-24 16:11:33 -08:00
2020-02-03 10:56:31 -08:00
template < class ElementType , std : : size_t Extent ,
2020-02-07 14:09:57 -08:00
std : : enable_if_t < ! std : : is_const < ElementType > : : value , int > = 0 >
2025-02-14 11:24:51 -06:00
span < BYTE_TYPE , details : : calculate_byte_size < ElementType , Extent > : : value >
2020-02-07 14:09:57 -08:00
as_writable_bytes ( span < ElementType , Extent > s ) noexcept
{
2025-02-14 11:24:51 -06:00
using type = span < BYTE_TYPE , details : : calculate_byte_size < ElementType , Extent > : : value > ;
2020-05-20 17:52:03 -07:00
2020-02-07 14:09:57 -08:00
// clang-format off
GSL_SUPPRESS ( type .1 ) // NO-FORMAT: attribute
// clang-format on
2025-02-14 11:24:51 -06:00
return type { reinterpret_cast < BYTE_TYPE * > ( s . data ( ) ) , s . size_bytes ( ) } ;
2020-02-07 14:09:57 -08:00
}
2016-02-24 11:26:28 -08:00
} // namespace gsl
2019-01-15 10:27:34 -08:00
# if defined(_MSC_VER) && !defined(__clang__)
2016-02-24 11:26:28 -08:00
2017-04-20 07:51:37 -07:00
# pragma warning(pop)
2016-02-24 11:26:28 -08:00
# endif // _MSC_VER
2019-01-15 10:27:34 -08:00
# if defined(__GNUC__) && __GNUC__ > 6
2018-06-08 20:41:06 +02:00
# pragma GCC diagnostic pop
# endif // __GNUC__ > 6
2024-10-12 02:46:21 +02:00
# if defined(__clang__)
# if __has_warning("-Wunsafe-buffer-usage")
2024-02-26 13:17:12 -08:00
# pragma clang diagnostic pop
2024-10-12 02:46:21 +02:00
# endif // __has_warning("-Wunsafe-buffer-usage")
# endif // defined(__clang__)
2024-02-26 13:17:12 -08:00
2016-02-24 11:26:28 -08:00
# endif // GSL_SPAN_H