2 // span for C++98 and later.
3 // Based on http://wg21.link/p0122r7
4 // For more information see https://github.com/martinmoene/span-lite
6 // Copyright 2018-2021 Martin Moene
8 // Distributed under the Boost Software License, Version 1.0.
9 // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 #ifndef NONSTD_SPAN_HPP_INCLUDED
12 #define NONSTD_SPAN_HPP_INCLUDED
14 #define span_lite_MAJOR 0
15 #define span_lite_MINOR 11
16 #define span_lite_PATCH 0
18 #define span_lite_VERSION span_STRINGIFY(span_lite_MAJOR) "." span_STRINGIFY(span_lite_MINOR) "." span_STRINGIFY(span_lite_PATCH)
20 #define span_STRINGIFY( x ) span_STRINGIFY_( x )
21 #define span_STRINGIFY_( x ) #x
23 // span configuration:
25 #define span_SPAN_DEFAULT 0
26 #define span_SPAN_NONSTD 1
27 #define span_SPAN_STD 2
29 // tweak header support:
32 # if __has_include(<nonstd/span.tweak.hpp>)
33 # include <nonstd/span.tweak.hpp>
35 #define span_HAVE_TWEAK_HEADER 1
37 #define span_HAVE_TWEAK_HEADER 0
38 //# pragma message("span.hpp: Note: Tweak header not supported.")
41 // span selection and configuration:
43 #define span_HAVE( feature ) ( span_HAVE_##feature )
45 #ifndef span_CONFIG_SELECT_SPAN
46 # define span_CONFIG_SELECT_SPAN ( span_HAVE_STD_SPAN ? span_SPAN_STD : span_SPAN_NONSTD )
49 #ifndef span_CONFIG_EXTENT_TYPE
50 # define span_CONFIG_EXTENT_TYPE std::size_t
53 #ifndef span_CONFIG_SIZE_TYPE
54 # define span_CONFIG_SIZE_TYPE std::size_t
57 #ifdef span_CONFIG_INDEX_TYPE
58 # error `span_CONFIG_INDEX_TYPE` is deprecated since v0.7.0; it is replaced by `span_CONFIG_SIZE_TYPE`.
61 // span configuration (features):
63 #ifndef span_FEATURE_WITH_INITIALIZER_LIST_P2447
64 # define span_FEATURE_WITH_INITIALIZER_LIST_P2447 0
67 #ifndef span_FEATURE_WITH_CONTAINER
68 #ifdef span_FEATURE_WITH_CONTAINER_TO_STD
69 # define span_FEATURE_WITH_CONTAINER span_IN_STD( span_FEATURE_WITH_CONTAINER_TO_STD )
71 # define span_FEATURE_WITH_CONTAINER 0
72 # define span_FEATURE_WITH_CONTAINER_TO_STD 0
76 #ifndef span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE
77 # define span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE 0
80 #ifndef span_FEATURE_MEMBER_AT
81 # define span_FEATURE_MEMBER_AT 0
84 #ifndef span_FEATURE_MEMBER_BACK_FRONT
85 # define span_FEATURE_MEMBER_BACK_FRONT 1
88 #ifndef span_FEATURE_MEMBER_CALL_OPERATOR
89 # define span_FEATURE_MEMBER_CALL_OPERATOR 0
92 #ifndef span_FEATURE_MEMBER_SWAP
93 # define span_FEATURE_MEMBER_SWAP 0
96 #ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB
97 # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB 0
98 #elif span_FEATURE_NON_MEMBER_FIRST_LAST_SUB
99 # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 1
100 # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 1
103 #ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN
104 # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 0
107 #ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER
108 # define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 0
111 #ifndef span_FEATURE_COMPARISON
112 # define span_FEATURE_COMPARISON 0 // Note: C++20 does not provide comparison
115 #ifndef span_FEATURE_SAME
116 # define span_FEATURE_SAME 0
119 #if span_FEATURE_SAME && !span_FEATURE_COMPARISON
120 # error `span_FEATURE_SAME` requires `span_FEATURE_COMPARISON`
123 #ifndef span_FEATURE_MAKE_SPAN
124 #ifdef span_FEATURE_MAKE_SPAN_TO_STD
125 # define span_FEATURE_MAKE_SPAN span_IN_STD( span_FEATURE_MAKE_SPAN_TO_STD )
127 # define span_FEATURE_MAKE_SPAN 0
128 # define span_FEATURE_MAKE_SPAN_TO_STD 0
132 #ifndef span_FEATURE_BYTE_SPAN
133 # define span_FEATURE_BYTE_SPAN 0
136 // Control presence of exception handling (try and auto discover):
138 #ifndef span_CONFIG_NO_EXCEPTIONS
139 # if defined(_MSC_VER)
140 # include <cstddef> // for _HAS_EXCEPTIONS
142 # if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
143 # define span_CONFIG_NO_EXCEPTIONS 0
145 # define span_CONFIG_NO_EXCEPTIONS 1
146 # undef span_CONFIG_CONTRACT_VIOLATION_THROWS
147 # undef span_CONFIG_CONTRACT_VIOLATION_TERMINATES
148 # define span_CONFIG_CONTRACT_VIOLATION_THROWS 0
149 # define span_CONFIG_CONTRACT_VIOLATION_TERMINATES 1
153 // Control pre- and postcondition violation behaviour:
155 #if defined( span_CONFIG_CONTRACT_LEVEL_ON )
156 # define span_CONFIG_CONTRACT_LEVEL_MASK 0x11
157 #elif defined( span_CONFIG_CONTRACT_LEVEL_OFF )
158 # define span_CONFIG_CONTRACT_LEVEL_MASK 0x00
159 #elif defined( span_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY )
160 # define span_CONFIG_CONTRACT_LEVEL_MASK 0x01
161 #elif defined( span_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY )
162 # define span_CONFIG_CONTRACT_LEVEL_MASK 0x10
164 # define span_CONFIG_CONTRACT_LEVEL_MASK 0x11
167 #if defined( span_CONFIG_CONTRACT_VIOLATION_THROWS )
168 # define span_CONFIG_CONTRACT_VIOLATION_THROWS_V span_CONFIG_CONTRACT_VIOLATION_THROWS
170 # define span_CONFIG_CONTRACT_VIOLATION_THROWS_V 0
173 #if defined( span_CONFIG_CONTRACT_VIOLATION_THROWS ) && span_CONFIG_CONTRACT_VIOLATION_THROWS && \
174 defined( span_CONFIG_CONTRACT_VIOLATION_TERMINATES ) && span_CONFIG_CONTRACT_VIOLATION_TERMINATES
175 # error Please define none or one of span_CONFIG_CONTRACT_VIOLATION_THROWS and span_CONFIG_CONTRACT_VIOLATION_TERMINATES to 1, but not both.
178 // C++ language version detection (C++23 is speculative):
179 // Note: VC14.0/1900 (VS2015) lacks too much from C++14.
181 #ifndef span_CPLUSPLUS
182 # if defined(_MSVC_LANG ) && !defined(__clang__)
183 # define span_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
185 # define span_CPLUSPLUS __cplusplus
189 #define span_CPP98_OR_GREATER ( span_CPLUSPLUS >= 199711L )
190 #define span_CPP11_OR_GREATER ( span_CPLUSPLUS >= 201103L )
191 #define span_CPP14_OR_GREATER ( span_CPLUSPLUS >= 201402L )
192 #define span_CPP17_OR_GREATER ( span_CPLUSPLUS >= 201703L )
193 #define span_CPP20_OR_GREATER ( span_CPLUSPLUS >= 202002L )
194 #define span_CPP23_OR_GREATER ( span_CPLUSPLUS >= 202300L )
196 // C++ language version (represent 98 as 3):
198 #define span_CPLUSPLUS_V ( span_CPLUSPLUS / 100 - (span_CPLUSPLUS > 200000 ? 2000 : 1994) )
200 #define span_IN_STD( v ) ( ((v) == 98 ? 3 : (v)) >= span_CPLUSPLUS_V )
202 #define span_CONFIG( feature ) ( span_CONFIG_##feature )
203 #define span_FEATURE( feature ) ( span_FEATURE_##feature )
204 #define span_FEATURE_TO_STD( feature ) ( span_IN_STD( span_FEATURE( feature##_TO_STD ) ) )
206 // Use C++20 std::span if available and requested:
208 #if span_CPP20_OR_GREATER && defined(__has_include )
209 # if __has_include( <span> )
210 # define span_HAVE_STD_SPAN 1
212 # define span_HAVE_STD_SPAN 0
215 # define span_HAVE_STD_SPAN 0
218 #define span_USES_STD_SPAN ( (span_CONFIG_SELECT_SPAN == span_SPAN_STD) || ((span_CONFIG_SELECT_SPAN == span_SPAN_DEFAULT) && span_HAVE_STD_SPAN) )
221 // Use C++20 std::span:
224 #if span_USES_STD_SPAN
231 using std::dynamic_extent;
233 // Note: C++20 does not provide comparison
234 // using std::operator==;
235 // using std::operator!=;
236 // using std::operator<;
237 // using std::operator<=;
238 // using std::operator>;
239 // using std::operator>=;
240 } // namespace nonstd
242 #else // span_USES_STD_SPAN
246 // Compiler versions:
248 // MSVC++ 6.0 _MSC_VER == 1200 span_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
249 // MSVC++ 7.0 _MSC_VER == 1300 span_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
250 // MSVC++ 7.1 _MSC_VER == 1310 span_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
251 // MSVC++ 8.0 _MSC_VER == 1400 span_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
252 // MSVC++ 9.0 _MSC_VER == 1500 span_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
253 // MSVC++ 10.0 _MSC_VER == 1600 span_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
254 // MSVC++ 11.0 _MSC_VER == 1700 span_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
255 // MSVC++ 12.0 _MSC_VER == 1800 span_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
256 // MSVC++ 14.0 _MSC_VER == 1900 span_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
257 // MSVC++ 14.1 _MSC_VER >= 1910 span_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
258 // MSVC++ 14.2 _MSC_VER >= 1920 span_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
260 #if defined(_MSC_VER ) && !defined(__clang__)
261 # define span_COMPILER_MSVC_VER (_MSC_VER )
262 # define span_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
264 # define span_COMPILER_MSVC_VER 0
265 # define span_COMPILER_MSVC_VERSION 0
268 #define span_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
270 #if defined(__clang__)
271 # define span_COMPILER_CLANG_VERSION span_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
273 # define span_COMPILER_CLANG_VERSION 0
276 #if defined(__GNUC__) && !defined(__clang__)
277 # define span_COMPILER_GNUC_VERSION span_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
279 # define span_COMPILER_GNUC_VERSION 0
282 // half-open range [lo..hi):
283 #define span_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
285 // Compiler warning suppression:
287 #if defined(__clang__)
288 # pragma clang diagnostic push
289 # pragma clang diagnostic ignored "-Wundef"
290 # pragma clang diagnostic ignored "-Wmismatched-tags"
291 # define span_RESTORE_WARNINGS() _Pragma( "clang diagnostic pop" )
293 #elif defined __GNUC__
294 # pragma GCC diagnostic push
295 # pragma GCC diagnostic ignored "-Wundef"
296 # define span_RESTORE_WARNINGS() _Pragma( "GCC diagnostic pop" )
298 #elif span_COMPILER_MSVC_VER >= 1900
299 # define span_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes))
300 # define span_RESTORE_WARNINGS() __pragma(warning(pop ))
302 // Suppress the following MSVC GSL warnings:
303 // - C26439, gsl::f.6 : special function 'function' can be declared 'noexcept'
304 // - C26440, gsl::f.6 : function 'function' can be declared 'noexcept'
305 // - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
306 // use brace initialization, gsl::narrow_cast or gsl::narrow
307 // - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same
308 // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
309 // - C26490: gsl::t.1 : don't use reinterpret_cast
311 span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 )
314 # define span_RESTORE_WARNINGS() /*empty*/
317 // Presence of language and library features:
320 # define span_HAS_CPP0X _HAS_CPP0X
322 # define span_HAS_CPP0X 0
325 #define span_CPP11_80 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1400)
326 #define span_CPP11_90 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1500)
327 #define span_CPP11_100 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1600)
328 #define span_CPP11_110 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1700)
329 #define span_CPP11_120 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1800)
330 #define span_CPP11_140 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1900)
332 #define span_CPP14_000 (span_CPP14_OR_GREATER)
333 #define span_CPP14_120 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1800)
334 #define span_CPP14_140 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1900)
336 #define span_CPP17_000 (span_CPP17_OR_GREATER)
338 // Presence of C++11 language features:
340 #define span_HAVE_ALIAS_TEMPLATE span_CPP11_140
341 #define span_HAVE_AUTO span_CPP11_100
342 #define span_HAVE_CONSTEXPR_11 span_CPP11_140
343 #define span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG span_CPP11_120
344 #define span_HAVE_EXPLICIT_CONVERSION span_CPP11_140
345 #define span_HAVE_INITIALIZER_LIST span_CPP11_120
346 #define span_HAVE_IS_DEFAULT span_CPP11_140
347 #define span_HAVE_IS_DELETE span_CPP11_140
348 #define span_HAVE_NOEXCEPT span_CPP11_140
349 #define span_HAVE_NORETURN ( span_CPP11_140 && ! span_BETWEEN( span_COMPILER_GNUC_VERSION, 1, 480 ) )
350 #define span_HAVE_NULLPTR span_CPP11_100
351 #define span_HAVE_STATIC_ASSERT span_CPP11_100
353 // Presence of C++14 language features:
355 #define span_HAVE_CONSTEXPR_14 span_CPP14_000
357 // Presence of C++17 language features:
359 #define span_HAVE_DEPRECATED span_CPP17_000
360 #define span_HAVE_NODISCARD span_CPP17_000
362 // MSVC: template parameter deduction guides since Visual Studio 2017 v15.7
364 #if defined(__cpp_deduction_guides)
365 # define span_HAVE_DEDUCTION_GUIDES 1
367 # define span_HAVE_DEDUCTION_GUIDES (span_CPP17_OR_GREATER && ! span_BETWEEN( span_COMPILER_MSVC_VER, 1, 1913 ))
370 // Presence of C++ library features:
372 #define span_HAVE_ADDRESSOF span_CPP17_000
373 #define span_HAVE_ARRAY span_CPP11_110
374 #define span_HAVE_BYTE span_CPP17_000
375 #define span_HAVE_CONDITIONAL span_CPP11_120
376 #define span_HAVE_CONTAINER_DATA_METHOD (span_CPP11_140 || ( span_COMPILER_MSVC_VER >= 1500 && span_HAS_CPP0X ))
377 #define span_HAVE_DATA span_CPP17_000
378 #define span_HAVE_LONGLONG span_CPP11_80
379 #define span_HAVE_REMOVE_CONST span_CPP11_110
380 #define span_HAVE_SNPRINTF span_CPP11_140
381 #define span_HAVE_STRUCT_BINDING span_CPP11_120
382 #define span_HAVE_TYPE_TRAITS span_CPP11_90
384 // Presence of byte-lite:
386 #ifdef NONSTD_BYTE_LITE_HPP
387 # define span_HAVE_NONSTD_BYTE 1
389 # define span_HAVE_NONSTD_BYTE 0
392 // C++ feature usage:
394 #if span_HAVE_ADDRESSOF
395 # define span_ADDRESSOF(x) std::addressof(x)
397 # define span_ADDRESSOF(x) (&x)
400 #if span_HAVE_CONSTEXPR_11
401 # define span_constexpr constexpr
403 # define span_constexpr /*span_constexpr*/
406 #if span_HAVE_CONSTEXPR_14
407 # define span_constexpr14 constexpr
409 # define span_constexpr14 /*span_constexpr*/
412 #if span_HAVE_EXPLICIT_CONVERSION
413 # define span_explicit explicit
415 # define span_explicit /*explicit*/
418 #if span_HAVE_IS_DELETE
419 # define span_is_delete = delete
421 # define span_is_delete
424 #if span_HAVE_IS_DELETE
425 # define span_is_delete_access public
427 # define span_is_delete_access private
430 #if span_HAVE_NOEXCEPT && ! span_CONFIG_CONTRACT_VIOLATION_THROWS_V
431 # define span_noexcept noexcept
433 # define span_noexcept /*noexcept*/
436 #if span_HAVE_NULLPTR
437 # define span_nullptr nullptr
439 # define span_nullptr NULL
442 #if span_HAVE_DEPRECATED
443 # define span_deprecated(msg) [[deprecated(msg)]]
445 # define span_deprecated(msg) /*[[deprecated]]*/
448 #if span_HAVE_NODISCARD
449 # define span_nodiscard [[nodiscard]]
451 # define span_nodiscard /*[[nodiscard]]*/
454 #if span_HAVE_NORETURN
455 # define span_noreturn [[noreturn]]
457 # define span_noreturn /*[[noreturn]]*/
462 #define span_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
463 #define span_HAVE_ITERATOR_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
465 // Additional includes:
467 #if span_HAVE( ADDRESSOF )
471 #if span_HAVE( ARRAY )
475 #if span_HAVE( BYTE )
479 #if span_HAVE( DATA )
480 # include <iterator> // for std::data(), std::size()
483 #if span_HAVE( TYPE_TRAITS )
484 # include <type_traits>
487 #if ! span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
491 #if span_FEATURE( MEMBER_AT ) > 1
495 #if ! span_CONFIG( NO_EXCEPTIONS )
496 # include <stdexcept>
499 // Contract violation
501 #define span_ELIDE_CONTRACT_EXPECTS ( 0 == ( span_CONFIG_CONTRACT_LEVEL_MASK & 0x01 ) )
502 #define span_ELIDE_CONTRACT_ENSURES ( 0 == ( span_CONFIG_CONTRACT_LEVEL_MASK & 0x10 ) )
504 #if span_ELIDE_CONTRACT_EXPECTS
505 # define span_constexpr_exp span_constexpr
506 # define span_EXPECTS( cond ) /* Expect elided */
508 # define span_constexpr_exp span_constexpr14
509 # define span_EXPECTS( cond ) span_CONTRACT_CHECK( "Precondition", cond )
512 #if span_ELIDE_CONTRACT_ENSURES
513 # define span_constexpr_ens span_constexpr
514 # define span_ENSURES( cond ) /* Ensures elided */
516 # define span_constexpr_ens span_constexpr14
517 # define span_ENSURES( cond ) span_CONTRACT_CHECK( "Postcondition", cond )
520 #define span_CONTRACT_CHECK( type, cond ) \
521 cond ? static_cast< void >( 0 ) \
522 : nonstd::span_lite::detail::report_contract_violation( span_LOCATION( __FILE__, __LINE__ ) ": " type " violation." )
525 # define span_LOCATION( file, line ) file ":" span_STRINGIFY( line )
527 # define span_LOCATION( file, line ) file "(" span_STRINGIFY( line ) ")"
532 #if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
534 #define span_REQUIRES_0(VA) \
535 template< bool B = (VA), typename std::enable_if<B, int>::type = 0 >
537 # if span_BETWEEN( span_COMPILER_MSVC_VERSION, 1, 140 )
538 // VS 2013 and earlier seem to have trouble with SFINAE for default non-type arguments
539 # define span_REQUIRES_T(VA) \
540 , typename = typename std::enable_if< ( VA ), nonstd::span_lite::detail::enabler >::type
542 # define span_REQUIRES_T(VA) \
543 , typename std::enable_if< (VA), int >::type = 0
546 #define span_REQUIRES_R(R, VA) \
547 typename std::enable_if< (VA), R>::type
549 #define span_REQUIRES_A(VA) \
550 , typename std::enable_if< (VA), void*>::type = nullptr
554 # define span_REQUIRES_0(VA) /*empty*/
555 # define span_REQUIRES_T(VA) /*empty*/
556 # define span_REQUIRES_R(R, VA) R
557 # define span_REQUIRES_A(VA) /*empty*/
562 namespace span_lite {
564 // [views.constants], constants
566 typedef span_CONFIG_EXTENT_TYPE extent_t;
567 typedef span_CONFIG_SIZE_TYPE size_t;
569 span_constexpr const extent_t dynamic_extent = static_cast<extent_t>( -1 );
571 template< class T, extent_t Extent = dynamic_extent >
574 // Tag to select span constructor taking a container (prevent ms-gsl warning C26426):
576 struct with_container_t { span_constexpr with_container_t() span_noexcept {} };
577 const span_constexpr with_container_t with_container;
583 #if span_HAVE( REMOVE_CONST )
585 using std::remove_cv;
586 using std::remove_const;
587 using std::remove_volatile;
591 template< class T > struct remove_const { typedef T type; };
592 template< class T > struct remove_const< T const > { typedef T type; };
594 template< class T > struct remove_volatile { typedef T type; };
595 template< class T > struct remove_volatile< T volatile > { typedef T type; };
600 typedef typename std11::remove_volatile< typename std11::remove_const< T >::type >::type type;
603 #endif // span_HAVE( REMOVE_CONST )
605 #if span_HAVE( TYPE_TRAITS )
608 using std::is_signed;
609 using std::integral_constant;
610 using std::true_type;
611 using std::false_type;
612 using std::remove_reference;
616 template< class T, T v > struct integral_constant { enum { value = v }; };
617 typedef integral_constant< bool, true > true_type;
618 typedef integral_constant< bool, false > false_type;
620 template< class T, class U > struct is_same : false_type{};
621 template< class T > struct is_same<T, T> : true_type{};
623 template< typename T > struct is_signed : false_type {};
624 template<> struct is_signed<signed char> : true_type {};
625 template<> struct is_signed<signed int > : true_type {};
626 template<> struct is_signed<signed long> : true_type {};
636 template< bool v > struct bool_constant : std11::integral_constant<bool, v>{};
645 #if span_HAVE( DATA )
650 #elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
652 template< typename T, std::size_t N >
653 inline span_constexpr auto size( const T(&)[N] ) span_noexcept -> size_t
658 template< typename C >
659 inline span_constexpr auto size( C const & cont ) -> decltype( cont.size() )
664 template< typename T, std::size_t N >
665 inline span_constexpr auto data( T(&arr)[N] ) span_noexcept -> T*
670 template< typename C >
671 inline span_constexpr auto data( C & cont ) -> decltype( cont.data() )
676 template< typename C >
677 inline span_constexpr auto data( C const & cont ) -> decltype( cont.data() )
682 template< typename E >
683 inline span_constexpr auto data( std::initializer_list<E> il ) span_noexcept -> E const *
688 #endif // span_HAVE( DATA )
690 #if span_HAVE( BYTE )
692 #elif span_HAVE( NONSTD_BYTE )
702 #if span_HAVE( DEDUCTION_GUIDES )
704 using iter_reference_t = decltype( *std::declval<T&>() );
709 // Implementation details:
713 /*enum*/ struct enabler{};
715 template< typename T >
716 span_constexpr bool is_positive( T x )
718 return std11::is_signed<T>::value ? x >= 0 : true;
721 #if span_HAVE( TYPE_TRAITS )
724 struct is_span_oracle : std::false_type{};
726 template< class T, span_CONFIG_EXTENT_TYPE Extent >
727 struct is_span_oracle< span<T, Extent> > : std::true_type{};
730 struct is_span : is_span_oracle< typename std::remove_cv<Q>::type >{};
733 struct is_std_array_oracle : std::false_type{};
735 #if span_HAVE( ARRAY )
737 template< class T, std::size_t Extent >
738 struct is_std_array_oracle< std::array<T, Extent> > : std::true_type{};
743 struct is_std_array : is_std_array_oracle< typename std::remove_cv<Q>::type >{};
746 struct is_array : std::false_type {};
749 struct is_array<T[]> : std::true_type {};
751 template< class T, std::size_t N >
752 struct is_array<T[N]> : std::true_type {};
754 #if span_CPP11_140 && ! span_BETWEEN( span_COMPILER_GNUC_VERSION, 1, 500 )
756 template< class, class = void >
757 struct has_size_and_data : std::false_type{};
760 struct has_size_and_data
763 decltype( std17::size(std::declval<C>()) ),
764 decltype( std17::data(std::declval<C>()) ) >
765 > : std::true_type{};
767 template< class, class, class = void >
768 struct is_compatible_element : std::false_type {};
770 template< class C, class E >
771 struct is_compatible_element
774 decltype( std17::data(std::declval<C>()) ) >
775 > : std::is_convertible< typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[], E(*)[] >{};
778 struct is_container : std17::bool_constant
780 ! is_span< C >::value
781 && ! is_array< C >::value
782 && ! is_std_array< C >::value
783 && has_size_and_data< C >::value
786 template< class C, class E >
787 struct is_compatible_container : std17::bool_constant
789 is_container<C>::value
790 && is_compatible_element<C,E>::value
793 #else // span_CPP11_140
798 ! is_span< C >::value
799 && ! is_array< C >::value
800 && ! is_std_array< C >::value
801 && ( std::is_convertible< typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[], E(*)[] >::value)
802 // && has_size_and_data< C >::value
804 , class = decltype( std17::size(std::declval<C>()) )
805 , class = decltype( std17::data(std::declval<C>()) )
807 struct is_compatible_container : std::true_type{};
809 #endif // span_CPP11_140
811 #endif // span_HAVE( TYPE_TRAITS )
813 #if ! span_CONFIG( NO_EXCEPTIONS )
814 #if span_FEATURE( MEMBER_AT ) > 1
816 // format index and size:
818 #if defined(__clang__)
819 # pragma clang diagnostic ignored "-Wlong-long"
820 #elif defined __GNUC__
821 # pragma GCC diagnostic ignored "-Wformat=ll"
822 # pragma GCC diagnostic ignored "-Wlong-long"
825 span_noreturn inline void throw_out_of_range( size_t idx, size_t size )
827 const char fmt[] = "span::at(): index '%lli' is out of range [0..%lli)";
828 char buffer[ 2 * 20 + sizeof fmt ];
829 sprintf( buffer, fmt, static_cast<long long>(idx), static_cast<long long>(size) );
831 throw std::out_of_range( buffer );
836 span_noreturn inline void throw_out_of_range( size_t /*idx*/, size_t /*size*/ )
838 throw std::out_of_range( "span::at(): index outside span" );
841 #endif // NO_EXCEPTIONS
843 #if span_CONFIG( CONTRACT_VIOLATION_THROWS_V )
845 struct contract_violation : std::logic_error
847 explicit contract_violation( char const * const message )
848 : std::logic_error( message )
852 inline void report_contract_violation( char const * msg )
854 throw contract_violation( msg );
857 #else // span_CONFIG( CONTRACT_VIOLATION_THROWS_V )
859 span_noreturn inline void report_contract_violation( char const * /*msg*/ ) span_noexcept
864 #endif // span_CONFIG( CONTRACT_VIOLATION_THROWS_V )
866 } // namespace detail
868 // Prevent signed-unsigned mismatch:
870 #define span_sizeof(T) static_cast<extent_t>( sizeof(T) )
873 inline span_constexpr size_t to_size( T size )
875 return static_cast<size_t>( size );
879 // [views.span] - A view over a contiguous, single-dimension sequence of objects
881 template< class T, extent_t Extent /*= dynamic_extent*/ >
885 // constants and types
887 typedef T element_type;
888 typedef typename std11::remove_cv< T >::type value_type;
890 typedef T & reference;
892 typedef T const * const_pointer;
893 typedef T const & const_reference;
895 typedef size_t size_type;
896 typedef extent_t extent_type;
898 typedef pointer iterator;
899 typedef const_pointer const_iterator;
901 typedef std::ptrdiff_t difference_type;
903 typedef std::reverse_iterator< iterator > reverse_iterator;
904 typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
906 // static constexpr extent_type extent = Extent;
907 enum { extent = Extent };
909 // 26.7.3.2 Constructors, copy, and assignment [span.cons]
913 ( Extent == dynamic_extent )
915 span_constexpr span() span_noexcept
916 : data_( span_nullptr )
919 // span_EXPECTS( data() == span_nullptr );
920 // span_EXPECTS( size() == 0 );
923 #if span_HAVE( ITERATOR_CTOR )
924 // Didn't yet succeed in combining the next two constructors:
926 span_constexpr_exp span( std::nullptr_t, size_type count )
927 : data_( span_nullptr )
930 span_EXPECTS( data_ == span_nullptr && count == 0 );
933 template< typename It
935 std::is_convertible<decltype(*std::declval<It&>()), element_type &>::value
938 span_constexpr_exp span( It first, size_type count )
939 : data_( to_address( first ) )
943 ( data_ == span_nullptr && count == 0 ) ||
944 ( data_ != span_nullptr && detail::is_positive( count ) )
948 span_constexpr_exp span( pointer ptr, size_type count )
953 ( ptr == span_nullptr && count == 0 ) ||
954 ( ptr != span_nullptr && detail::is_positive( count ) )
959 #if span_HAVE( ITERATOR_CTOR )
960 template< typename It, typename End
962 std::is_convertible<decltype(&*std::declval<It&>()), element_type *>::value
963 && ! std::is_convertible<End, std::size_t>::value
966 span_constexpr_exp span( It first, End last )
967 : data_( to_address( first ) )
968 , size_( to_size( last - first ) )
975 span_constexpr_exp span( pointer first, pointer last )
977 , size_( to_size( last - first ) )
985 template< std::size_t N
987 (Extent == dynamic_extent || Extent == static_cast<extent_t>(N))
988 && std::is_convertible< value_type(*)[], element_type(*)[] >::value
991 span_constexpr span( element_type ( &arr )[ N ] ) span_noexcept
992 : data_( span_ADDRESSOF( arr[0] ) )
996 #if span_HAVE( ARRAY )
998 template< std::size_t N
1000 (Extent == dynamic_extent || Extent == static_cast<extent_t>(N))
1001 && std::is_convertible< value_type(*)[], element_type(*)[] >::value
1004 # if span_FEATURE( CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE )
1005 span_constexpr span( std::array< element_type, N > & arr ) span_noexcept
1007 span_constexpr span( std::array< value_type, N > & arr ) span_noexcept
1009 : data_( arr.data() )
1010 , size_( to_size( arr.size() ) )
1013 template< std::size_t N
1014 # if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
1016 (Extent == dynamic_extent || Extent == static_cast<extent_t>(N))
1017 && std::is_convertible< value_type(*)[], element_type(*)[] >::value
1021 span_constexpr span( std::array< value_type, N> const & arr ) span_noexcept
1022 : data_( arr.data() )
1023 , size_( to_size( arr.size() ) )
1026 #endif // span_HAVE( ARRAY )
1028 #if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
1029 template< class Container
1031 detail::is_compatible_container< Container, element_type >::value
1034 span_constexpr span( Container & cont )
1035 : data_( std17::data( cont ) )
1036 , size_( to_size( std17::size( cont ) ) )
1039 template< class Container
1041 std::is_const< element_type >::value
1042 && detail::is_compatible_container< Container, element_type >::value
1045 span_constexpr span( Container const & cont )
1046 : data_( std17::data( cont ) )
1047 , size_( to_size( std17::size( cont ) ) )
1050 #endif // span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
1052 #if span_FEATURE( WITH_CONTAINER )
1054 template< class Container >
1055 span_constexpr span( with_container_t, Container & cont )
1056 : data_( cont.size() == 0 ? span_nullptr : span_ADDRESSOF( cont[0] ) )
1057 , size_( to_size( cont.size() ) )
1060 template< class Container >
1061 span_constexpr span( with_container_t, Container const & cont )
1062 : data_( cont.size() == 0 ? span_nullptr : const_cast<pointer>( span_ADDRESSOF( cont[0] ) ) )
1063 , size_( to_size( cont.size() ) )
1067 #if span_FEATURE( WITH_INITIALIZER_LIST_P2447 ) && span_HAVE( INITIALIZER_LIST )
1069 // constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il) noexcept;
1071 #if !span_BETWEEN( span_COMPILER_MSVC_VERSION, 120, 130 )
1073 template< extent_t U = Extent
1078 #if span_COMPILER_GNUC_VERSION >= 900 // prevent GCC's "-Winit-list-lifetime"
1079 span_constexpr14 explicit span( std::initializer_list<value_type> il ) span_noexcept
1085 span_constexpr explicit span( std::initializer_list<value_type> il ) span_noexcept
1086 : data_( il.begin() )
1087 , size_( il.size() )
1091 #endif // MSVC 120 (VS2013)
1093 template< extent_t U = Extent
1098 #if span_COMPILER_GNUC_VERSION >= 900 // prevent GCC's "-Winit-list-lifetime"
1099 span_constexpr14 /*explicit*/ span( std::initializer_list<value_type> il ) span_noexcept
1105 span_constexpr /*explicit*/ span( std::initializer_list<value_type> il ) span_noexcept
1106 : data_( il.begin() )
1107 , size_( il.size() )
1113 #if span_HAVE( IS_DEFAULT )
1114 span_constexpr span( span const & other ) span_noexcept = default;
1116 ~span() span_noexcept = default;
1118 span_constexpr14 span & operator=( span const & other ) span_noexcept = default;
1120 span_constexpr span( span const & other ) span_noexcept
1121 : data_( other.data_ )
1122 , size_( other.size_ )
1125 ~span() span_noexcept
1128 span_constexpr14 span & operator=( span const & other ) span_noexcept
1130 data_ = other.data_;
1131 size_ = other.size_;
1137 template< class OtherElementType, extent_type OtherExtent
1139 (Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent)
1140 && std::is_convertible<OtherElementType(*)[], element_type(*)[]>::value
1143 span_constexpr_exp span( span<OtherElementType, OtherExtent> const & other ) span_noexcept
1144 : data_( other.data() )
1145 , size_( other.size() )
1147 span_EXPECTS( OtherExtent == dynamic_extent || other.size() == to_size(OtherExtent) );
1150 // 26.7.3.3 Subviews [span.sub]
1152 template< extent_type Count >
1153 span_constexpr_exp span< element_type, Count >
1156 span_EXPECTS( detail::is_positive( Count ) && Count <= size() );
1158 return span< element_type, Count >( data(), Count );
1161 template< extent_type Count >
1162 span_constexpr_exp span< element_type, Count >
1165 span_EXPECTS( detail::is_positive( Count ) && Count <= size() );
1167 return span< element_type, Count >( data() + (size() - Count), Count );
1170 #if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
1171 template< size_type Offset, extent_type Count = dynamic_extent >
1173 template< size_type Offset, extent_type Count /*= dynamic_extent*/ >
1175 span_constexpr_exp span< element_type, Count >
1179 ( detail::is_positive( Offset ) && Offset <= size() ) &&
1180 ( Count == dynamic_extent || (detail::is_positive( Count ) && Count + Offset <= size()) )
1183 return span< element_type, Count >(
1184 data() + Offset, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : size() - Offset) );
1187 span_constexpr_exp span< element_type, dynamic_extent >
1188 first( size_type count ) const
1190 span_EXPECTS( detail::is_positive( count ) && count <= size() );
1192 return span< element_type, dynamic_extent >( data(), count );
1195 span_constexpr_exp span< element_type, dynamic_extent >
1196 last( size_type count ) const
1198 span_EXPECTS( detail::is_positive( count ) && count <= size() );
1200 return span< element_type, dynamic_extent >( data() + ( size() - count ), count );
1203 span_constexpr_exp span< element_type, dynamic_extent >
1204 subspan( size_type offset, size_type count = static_cast<size_type>(dynamic_extent) ) const
1207 ( ( detail::is_positive( offset ) && offset <= size() ) ) &&
1208 ( count == static_cast<size_type>(dynamic_extent) || ( detail::is_positive( count ) && offset + count <= size() ) )
1211 return span< element_type, dynamic_extent >(
1212 data() + offset, count == static_cast<size_type>(dynamic_extent) ? size() - offset : count );
1215 // 26.7.3.4 Observers [span.obs]
1217 span_constexpr size_type size() const span_noexcept
1222 span_constexpr std::ptrdiff_t ssize() const span_noexcept
1224 return static_cast<std::ptrdiff_t>( size_ );
1227 span_constexpr size_type size_bytes() const span_noexcept
1229 return size() * to_size( sizeof( element_type ) );
1232 span_nodiscard span_constexpr bool empty() const span_noexcept
1237 // 26.7.3.5 Element access [span.elem]
1239 span_constexpr_exp reference operator[]( size_type idx ) const
1241 span_EXPECTS( detail::is_positive( idx ) && idx < size() );
1243 return *( data() + idx );
1246 #if span_FEATURE( MEMBER_CALL_OPERATOR )
1247 span_deprecated("replace operator() with operator[]")
1249 span_constexpr_exp reference operator()( size_type idx ) const
1251 span_EXPECTS( detail::is_positive( idx ) && idx < size() );
1253 return *( data() + idx );
1257 #if span_FEATURE( MEMBER_AT )
1258 span_constexpr14 reference at( size_type idx ) const
1260 #if span_CONFIG( NO_EXCEPTIONS )
1261 return this->operator[]( idx );
1263 if ( !detail::is_positive( idx ) || size() <= idx )
1265 detail::throw_out_of_range( idx, size() );
1267 return *( data() + idx );
1272 span_constexpr pointer data() const span_noexcept
1277 #if span_FEATURE( MEMBER_BACK_FRONT )
1279 span_constexpr_exp reference front() const span_noexcept
1281 span_EXPECTS( ! empty() );
1286 span_constexpr_exp reference back() const span_noexcept
1288 span_EXPECTS( ! empty() );
1290 return *( data() + size() - 1 );
1295 // xx.x.x.x Modifiers [span.modifiers]
1297 #if span_FEATURE( MEMBER_SWAP )
1299 span_constexpr14 void swap( span & other ) span_noexcept
1302 swap( data_, other.data_ );
1303 swap( size_, other.size_ );
1307 // 26.7.3.6 Iterator support [span.iterators]
1309 span_constexpr iterator begin() const span_noexcept
1311 #if span_CPP11_OR_GREATER
1314 return iterator( data() );
1318 span_constexpr iterator end() const span_noexcept
1320 #if span_CPP11_OR_GREATER
1321 return { data() + size() };
1323 return iterator( data() + size() );
1327 span_constexpr const_iterator cbegin() const span_noexcept
1329 #if span_CPP11_OR_GREATER
1332 return const_iterator( data() );
1336 span_constexpr const_iterator cend() const span_noexcept
1338 #if span_CPP11_OR_GREATER
1339 return { data() + size() };
1341 return const_iterator( data() + size() );
1345 span_constexpr reverse_iterator rbegin() const span_noexcept
1347 return reverse_iterator( end() );
1350 span_constexpr reverse_iterator rend() const span_noexcept
1352 return reverse_iterator( begin() );
1355 span_constexpr const_reverse_iterator crbegin() const span_noexcept
1357 return const_reverse_iterator ( cend() );
1360 span_constexpr const_reverse_iterator crend() const span_noexcept
1362 return const_reverse_iterator( cbegin() );
1367 // Note: C++20 has std::pointer_traits<Ptr>::to_address( it );
1369 #if span_HAVE( ITERATOR_CTOR )
1370 static inline span_constexpr pointer to_address( std::nullptr_t ) span_noexcept
1375 template< typename U >
1376 static inline span_constexpr U * to_address( U * p ) span_noexcept
1381 template< typename Ptr
1382 span_REQUIRES_T(( ! std::is_pointer<Ptr>::value ))
1384 static inline span_constexpr pointer to_address( Ptr const & it ) span_noexcept
1386 return to_address( it.operator->() );
1388 #endif // span_HAVE( ITERATOR_CTOR )
1395 // class template argument deduction guides:
1397 #if span_HAVE( DEDUCTION_GUIDES )
1399 template< class T, size_t N >
1400 span( T (&)[N] ) -> span<T, static_cast<extent_t>(N)>;
1402 template< class T, size_t N >
1403 span( std::array<T, N> & ) -> span<T, static_cast<extent_t>(N)>;
1405 template< class T, size_t N >
1406 span( std::array<T, N> const & ) -> span<const T, static_cast<extent_t>(N)>;
1408 #if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
1410 template< class Container >
1411 span( Container& ) -> span<typename Container::value_type>;
1413 template< class Container >
1414 span( Container const & ) -> span<const typename Container::value_type>;
1418 // iterator: constraints: It satisfies contiguous_Âiterator.
1420 template< class It, class EndOrSize >
1421 span( It, EndOrSize ) -> span< typename std11::remove_reference< typename std20::iter_reference_t<It> >::type >;
1423 #endif // span_HAVE( DEDUCTION_GUIDES )
1425 // 26.7.3.7 Comparison operators [span.comparison]
1427 #if span_FEATURE( COMPARISON )
1428 #if span_FEATURE( SAME )
1430 template< class T1, extent_t E1, class T2, extent_t E2 >
1431 inline span_constexpr bool same( span<T1,E1> const & l, span<T2,E2> const & r ) span_noexcept
1433 return std11::is_same<T1, T2>::value
1434 && l.size() == r.size()
1435 && static_cast<void const*>( l.data() ) == r.data();
1440 template< class T1, extent_t E1, class T2, extent_t E2 >
1441 inline span_constexpr bool operator==( span<T1,E1> const & l, span<T2,E2> const & r )
1444 #if span_FEATURE( SAME )
1447 ( l.size() == r.size() && std::equal( l.begin(), l.end(), r.begin() ) );
1450 template< class T1, extent_t E1, class T2, extent_t E2 >
1451 inline span_constexpr bool operator<( span<T1,E1> const & l, span<T2,E2> const & r )
1453 return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
1456 template< class T1, extent_t E1, class T2, extent_t E2 >
1457 inline span_constexpr bool operator!=( span<T1,E1> const & l, span<T2,E2> const & r )
1462 template< class T1, extent_t E1, class T2, extent_t E2 >
1463 inline span_constexpr bool operator<=( span<T1,E1> const & l, span<T2,E2> const & r )
1468 template< class T1, extent_t E1, class T2, extent_t E2 >
1469 inline span_constexpr bool operator>( span<T1,E1> const & l, span<T2,E2> const & r )
1474 template< class T1, extent_t E1, class T2, extent_t E2 >
1475 inline span_constexpr bool operator>=( span<T1,E1> const & l, span<T2,E2> const & r )
1480 #endif // span_FEATURE( COMPARISON )
1482 // 26.7.2.6 views of object representation [span.objectrep]
1484 #if span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE )
1486 // Avoid MSVC 14.1 (1910), VS 2017: warning C4307: '*': integral constant overflow:
1488 template< typename T, extent_t Extent >
1491 #if span_CPP11_OR_GREATER
1492 enum ET : extent_t { value = span_sizeof(T) * Extent };
1494 enum ET { value = span_sizeof(T) * Extent };
1498 template< typename T >
1499 struct BytesExtent< T, dynamic_extent >
1501 #if span_CPP11_OR_GREATER
1502 enum ET : extent_t { value = dynamic_extent };
1504 enum ET { value = dynamic_extent };
1508 template< class T, extent_t Extent >
1509 inline span_constexpr span< const std17::byte, BytesExtent<T, Extent>::value >
1510 as_bytes( span<T,Extent> spn ) span_noexcept
1513 return { reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() };
1515 return span< const std17::byte, BytesExtent<T, Extent>::value >(
1516 reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() ); // NOLINT
1520 template< class T, extent_t Extent >
1521 inline span_constexpr span< std17::byte, BytesExtent<T, Extent>::value >
1522 as_writable_bytes( span<T,Extent> spn ) span_noexcept
1525 return { reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() };
1527 return span< std17::byte, BytesExtent<T, Extent>::value >(
1528 reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() ); // NOLINT
1532 #endif // span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE )
1534 // 27.8 Container and view access [iterator.container]
1536 template< class T, extent_t Extent /*= dynamic_extent*/ >
1537 span_constexpr std::size_t size( span<T,Extent> const & spn )
1539 return static_cast<std::size_t>( spn.size() );
1542 template< class T, extent_t Extent /*= dynamic_extent*/ >
1543 span_constexpr std::ptrdiff_t ssize( span<T,Extent> const & spn )
1545 return static_cast<std::ptrdiff_t>( spn.size() );
1548 } // namespace span_lite
1549 } // namespace nonstd
1551 // make available in nonstd:
1555 using span_lite::dynamic_extent;
1557 using span_lite::span;
1559 using span_lite::with_container;
1561 #if span_FEATURE( COMPARISON )
1562 #if span_FEATURE( SAME )
1563 using span_lite::same;
1566 using span_lite::operator==;
1567 using span_lite::operator!=;
1568 using span_lite::operator<;
1569 using span_lite::operator<=;
1570 using span_lite::operator>;
1571 using span_lite::operator>=;
1574 #if span_HAVE( BYTE )
1575 using span_lite::as_bytes;
1576 using span_lite::as_writable_bytes;
1579 using span_lite::size;
1580 using span_lite::ssize;
1582 } // namespace nonstd
1584 #endif // span_USES_STD_SPAN
1586 // make_span() [span-lite extension]:
1588 #if span_FEATURE( MAKE_SPAN ) || span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) || span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER )
1590 #if span_USES_STD_SPAN
1591 # define span_constexpr constexpr
1592 # define span_noexcept noexcept
1593 # define span_nullptr nullptr
1594 # ifndef span_CONFIG_EXTENT_TYPE
1595 # define span_CONFIG_EXTENT_TYPE std::size_t
1597 using extent_t = span_CONFIG_EXTENT_TYPE;
1598 #endif // span_USES_STD_SPAN
1601 namespace span_lite {
1604 inline span_constexpr span<T>
1605 make_span( T * ptr, size_t count ) span_noexcept
1607 return span<T>( ptr, count );
1611 inline span_constexpr span<T>
1612 make_span( T * first, T * last ) span_noexcept
1614 return span<T>( first, last );
1617 template< class T, std::size_t N >
1618 inline span_constexpr span<T, static_cast<extent_t>(N)>
1619 make_span( T ( &arr )[ N ] ) span_noexcept
1621 return span<T, static_cast<extent_t>(N)>( &arr[ 0 ], N );
1624 #if span_USES_STD_SPAN || span_HAVE( ARRAY )
1626 template< class T, std::size_t N >
1627 inline span_constexpr span<T, static_cast<extent_t>(N)>
1628 make_span( std::array< T, N > & arr ) span_noexcept
1630 return span<T, static_cast<extent_t>(N)>( arr );
1633 template< class T, std::size_t N >
1634 inline span_constexpr span< const T, static_cast<extent_t>(N) >
1635 make_span( std::array< T, N > const & arr ) span_noexcept
1637 return span<const T, static_cast<extent_t>(N)>( arr );
1640 #endif // span_HAVE( ARRAY )
1642 #if span_USES_STD_SPAN || span_HAVE( INITIALIZER_LIST )
1645 inline span_constexpr span< const T >
1646 make_span( std::initializer_list<T> il ) span_noexcept
1648 return span<const T>( il.begin(), il.size() );
1651 #endif // span_HAVE( INITIALIZER_LIST )
1653 #if span_USES_STD_SPAN
1655 template< class Container, class EP = decltype( std::data(std::declval<Container&>())) >
1656 inline span_constexpr auto
1657 make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer<EP>::type >
1659 return span< typename std::remove_pointer<EP>::type >( cont );
1662 template< class Container, class EP = decltype( std::data(std::declval<Container&>())) >
1663 inline span_constexpr auto
1664 make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer<EP>::type >
1666 return span< const typename std::remove_pointer<EP>::type >( cont );
1669 #elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) && span_HAVE( AUTO )
1671 template< class Container, class EP = decltype( std17::data(std::declval<Container&>())) >
1672 inline span_constexpr auto
1673 make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer<EP>::type >
1675 return span< typename std::remove_pointer<EP>::type >( cont );
1678 template< class Container, class EP = decltype( std17::data(std::declval<Container&>())) >
1679 inline span_constexpr auto
1680 make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer<EP>::type >
1682 return span< const typename std::remove_pointer<EP>::type >( cont );
1688 inline span_constexpr span<T>
1689 make_span( span<T> spn ) span_noexcept
1694 template< class T, class Allocator >
1695 inline span_constexpr span<T>
1696 make_span( std::vector<T, Allocator> & cont ) span_noexcept
1698 return span<T>( with_container, cont );
1701 template< class T, class Allocator >
1702 inline span_constexpr span<const T>
1703 make_span( std::vector<T, Allocator> const & cont ) span_noexcept
1705 return span<const T>( with_container, cont );
1708 #endif // span_USES_STD_SPAN || ( ... )
1710 #if ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER )
1712 template< class Container >
1713 inline span_constexpr span<typename Container::value_type>
1714 make_span( with_container_t, Container & cont ) span_noexcept
1716 return span< typename Container::value_type >( with_container, cont );
1719 template< class Container >
1720 inline span_constexpr span<const typename Container::value_type>
1721 make_span( with_container_t, Container const & cont ) span_noexcept
1723 return span< const typename Container::value_type >( with_container, cont );
1726 #endif // ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER )
1728 // extensions: non-member views:
1729 // this feature implies the presence of make_span()
1731 #if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN )
1733 template< extent_t Count, class T, extent_t Extent >
1734 span_constexpr span<T, Count>
1735 first( span<T, Extent> spn )
1737 return spn.template first<Count>();
1740 template< class T, extent_t Extent >
1741 span_constexpr span<T>
1742 first( span<T, Extent> spn, size_t count )
1744 return spn.first( count );
1747 template< extent_t Count, class T, extent_t Extent >
1748 span_constexpr span<T, Count>
1749 last( span<T, Extent> spn )
1751 return spn.template last<Count>();
1754 template< class T, extent_t Extent >
1755 span_constexpr span<T>
1756 last( span<T, Extent> spn, size_t count )
1758 return spn.last( count );
1761 template< size_t Offset, extent_t Count, class T, extent_t Extent >
1762 span_constexpr span<T, Count>
1763 subspan( span<T, Extent> spn )
1765 return spn.template subspan<Offset, Count>();
1768 template< class T, extent_t Extent >
1769 span_constexpr span<T>
1770 subspan( span<T, Extent> spn, size_t offset, extent_t count = dynamic_extent )
1772 return spn.subspan( offset, count );
1775 #endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN )
1777 #if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) && span_CPP11_120
1779 template< extent_t Count, class T >
1781 first( T & t ) -> decltype( make_span(t).template first<Count>() )
1783 return make_span( t ).template first<Count>();
1788 first( T & t, size_t count ) -> decltype( make_span(t).first(count) )
1790 return make_span( t ).first( count );
1793 template< extent_t Count, class T >
1795 last( T & t ) -> decltype( make_span(t).template last<Count>() )
1797 return make_span(t).template last<Count>();
1802 last( T & t, extent_t count ) -> decltype( make_span(t).last(count) )
1804 return make_span( t ).last( count );
1807 template< size_t Offset, extent_t Count = dynamic_extent, class T >
1809 subspan( T & t ) -> decltype( make_span(t).template subspan<Offset, Count>() )
1811 return make_span( t ).template subspan<Offset, Count>();
1816 subspan( T & t, size_t offset, extent_t count = dynamic_extent ) -> decltype( make_span(t).subspan(offset, count) )
1818 return make_span( t ).subspan( offset, count );
1821 #endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER )
1823 } // namespace span_lite
1824 } // namespace nonstd
1826 // make available in nonstd:
1829 using span_lite::make_span;
1831 #if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) || ( span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) && span_CPP11_120 )
1833 using span_lite::first;
1834 using span_lite::last;
1835 using span_lite::subspan;
1837 #endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_[SPAN|CONTAINER] )
1839 } // namespace nonstd
1841 #endif // #if span_FEATURE_TO_STD( MAKE_SPAN )
1843 #if span_CPP11_OR_GREATER && span_FEATURE( BYTE_SPAN ) && ( span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) )
1846 namespace span_lite {
1849 inline span_constexpr auto
1850 byte_span( T & t ) span_noexcept -> span< std17::byte, span_sizeof(T) >
1852 return span< std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte * >( &t ), span_sizeof(T) );
1856 inline span_constexpr auto
1857 byte_span( T const & t ) span_noexcept -> span< const std17::byte, span_sizeof(T) >
1859 return span< const std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte const * >( &t ), span_sizeof(T) );
1862 } // namespace span_lite
1863 } // namespace nonstd
1865 // make available in nonstd:
1868 using span_lite::byte_span;
1869 } // namespace nonstd
1871 #endif // span_FEATURE( BYTE_SPAN )
1873 #if !span_USES_STD_SPAN && span_HAVE( STRUCT_BINDING )
1875 #if span_CPP14_OR_GREATER
1877 #elif span_CPP11_OR_GREATER
1880 template< std::size_t I, typename T >
1881 using tuple_element_t = typename tuple_element<I, T>::type;
1885 template< typename T >
1886 class tuple_size; /*undefined*/
1888 template< std::size_t I, typename T >
1889 class tuple_element; /* undefined */
1891 #endif // span_CPP14_OR_GREATER
1895 // 26.7.X Tuple interface
1897 // std::tuple_size<>:
1899 template< typename ElementType, nonstd::span_lite::extent_t Extent >
1900 class tuple_size< nonstd::span<ElementType, Extent> > : public integral_constant<size_t, static_cast<size_t>(Extent)> {};
1902 // std::tuple_size<>: Leave undefined for dynamic extent:
1904 template< typename ElementType >
1905 class tuple_size< nonstd::span<ElementType, nonstd::dynamic_extent> >;
1907 // std::tuple_element<>:
1909 template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent >
1910 class tuple_element< I, nonstd::span<ElementType, Extent> >
1913 #if span_HAVE( STATIC_ASSERT )
1914 static_assert( Extent != nonstd::dynamic_extent && I < Extent, "tuple_element<I,span>: dynamic extent or index out of range" );
1916 using type = ElementType;
1919 // std::get<>(), 2 variants:
1921 template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent >
1922 span_constexpr ElementType & get( nonstd::span<ElementType, Extent> & spn ) span_noexcept
1924 #if span_HAVE( STATIC_ASSERT )
1925 static_assert( Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range" );
1930 template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent >
1931 span_constexpr ElementType const & get( nonstd::span<ElementType, Extent> const & spn ) span_noexcept
1933 #if span_HAVE( STATIC_ASSERT )
1934 static_assert( Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range" );
1939 } // end namespace std
1941 #endif // !span_USES_STD_SPAN && span_HAVE( STRUCT_BINDING )
1943 #if ! span_USES_STD_SPAN
1944 span_RESTORE_WARNINGS()
1945 #endif // span_USES_STD_SPAN
1947 #endif // NONSTD_SPAN_HPP_INCLUDED