zoneminder/dep/span-lite/include/span.hpp

1818 lines
50 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

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