3 #if __cplusplus >= 202000L
10 template <
typename A,
size_t E = std::dynamic_extent>
11 using span = std::span<A, E>;
27 #ifndef TCB_SPAN_HPP_INCLUDED
28 #define TCB_SPAN_HPP_INCLUDED
33 #include <type_traits>
35 #ifndef TCB_SPAN_NO_EXCEPTIONS
37 #if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND))
38 #define TCB_SPAN_NO_EXCEPTIONS
42 #ifndef TCB_SPAN_NO_EXCEPTIONS
49 #ifndef TCB_SPAN_NAMESPACE_NAME
50 #define TCB_SPAN_NAMESPACE_NAME tcb
53 #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
54 #define TCB_SPAN_HAVE_CPP17
57 #if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
58 #define TCB_SPAN_HAVE_CPP14
64 #if !defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) && \
65 !defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) && \
66 !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
67 #if defined(NDEBUG) || !defined(TCB_SPAN_HAVE_CPP14)
68 #define TCB_SPAN_NO_CONTRACT_CHECKING
70 #define TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION
74 #if defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION)
75 struct contract_violation_error : std::logic_error {
76 explicit contract_violation_error(
const char* msg) : std::logic_error(msg)
80 inline void contract_violation(
const char* msg)
82 throw contract_violation_error(msg);
85 #elif defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION)
86 [[noreturn]]
inline void contract_violation(
const char* )
92 #if !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
93 #define TCB_SPAN_STRINGIFY(cond) #cond
94 #define TCB_SPAN_EXPECT(cond) \
95 cond ? (void) 0 : contract_violation("Expected " TCB_SPAN_STRINGIFY(cond))
97 #define TCB_SPAN_EXPECT(cond)
100 #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_inline_variables)
101 #define TCB_SPAN_INLINE_VAR inline
103 #define TCB_SPAN_INLINE_VAR
106 #if defined(TCB_SPAN_HAVE_CPP14) || \
107 (defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
108 #define TCB_SPAN_HAVE_CPP14_CONSTEXPR
111 #if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR)
112 #define TCB_SPAN_CONSTEXPR14 constexpr
114 #define TCB_SPAN_CONSTEXPR14
117 #if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR) && \
118 (!defined(_MSC_VER) || _MSC_VER > 1900)
119 #define TCB_SPAN_CONSTEXPR_ASSIGN constexpr
121 #define TCB_SPAN_CONSTEXPR_ASSIGN
124 #if defined(TCB_SPAN_NO_CONTRACT_CHECKING)
125 #define TCB_SPAN_CONSTEXPR11 constexpr
127 #define TCB_SPAN_CONSTEXPR11 TCB_SPAN_CONSTEXPR14
130 #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_deduction_guides)
131 #define TCB_SPAN_HAVE_DEDUCTION_GUIDES
134 #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_byte)
135 #define TCB_SPAN_HAVE_STD_BYTE
138 #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_array_constexpr)
139 #define TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC
142 #if defined(TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC)
143 #define TCB_SPAN_ARRAY_CONSTEXPR constexpr
145 #define TCB_SPAN_ARRAY_CONSTEXPR
148 #ifdef TCB_SPAN_HAVE_STD_BYTE
151 using byte =
unsigned char;
154 #if defined(TCB_SPAN_HAVE_CPP17)
155 #define TCB_SPAN_NODISCARD [[nodiscard]]
157 #define TCB_SPAN_NODISCARD
162 template <
typename ElementType, std::
size_t Extent = dynamic_extent>
167 template <
typename E, std::
size_t S>
176 static constexpr std::size_t
size =
S;
179 template <
typename E>
192 #if defined(TCB_SPAN_HAVE_CPP17) || \
193 defined(__cpp_lib_nonmember_container_access)
198 constexpr
auto size(
const C& c) -> decltype(c.size())
203 template <
class T, std::
size_t N>
204 constexpr std::size_t
size(
const T (&)[N]) noexcept
210 constexpr
auto data(C& c) -> decltype(c.data())
216 constexpr
auto data(
const C& c) -> decltype(c.data())
221 template <
class T, std::
size_t N>
228 constexpr
const E*
data(std::initializer_list<E> il) noexcept
232 #endif // TCB_SPAN_HAVE_CPP17
234 #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_void_t)
237 template <
typename...>
241 template <
typename T>
248 template <
typename T, std::
size_t S>
254 template <
typename T, std::
size_t N>
257 template <
typename,
typename =
void>
260 template <
typename T>
262 decltype(detail::data(std::declval<T>()))>>
265 template <
typename C,
typename U = uncvref_t<C>>
272 template <
typename T>
275 template <
typename,
typename,
typename =
void>
278 template <
typename T,
typename E>
281 typename
std::enable_if<
282 !std::is_same<typename std::remove_cv<decltype(
283 detail::data(std::declval<T>()))>::type,
285 : std::is_convertible<
286 remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
289 template <
typename,
typename =
size_t>
292 template <
typename T>
297 template <
typename ElementType, std::
size_t Extent>
299 static_assert(std::is_object<ElementType>::value,
300 "A span's ElementType must be an object type (not a "
301 "reference type or void)");
303 "A span's ElementType must be a complete type (not a forward "
305 static_assert(!std::is_abstract<ElementType>::value,
306 "A span's ElementType cannot be an abstract class type");
339 :
storage_(first_elem, last_elem - first_elem)
342 last_elem - first_elem ==
343 static_cast<std::ptrdiff_t
>(
extent));
346 template <std::size_t N, std::size_t E =
Extent,
347 typename std::enable_if<
355 template <std::size_t N, std::size_t E =
Extent,
356 typename std::enable_if<
359 std::array<value_type, N>&, ElementType>::value,
365 template <std::size_t N, std::size_t E =
Extent,
366 typename std::enable_if<
369 const std::array<value_type, N>&, ElementType>::value,
376 typename Container, std::size_t E =
Extent,
377 typename std::enable_if<
380 Container&, ElementType>::value,
382 constexpr
span(Container& cont)
387 typename Container, std::size_t E =
Extent,
388 typename std::enable_if<
391 const Container&, ElementType>::value,
393 constexpr
span(
const Container& cont)
397 constexpr
span(
const span& other) noexcept =
default;
399 template <
typename OtherElementType, std::size_t OtherExtent,
400 typename std::enable_if<
402 std::is_convertible<OtherElementType (*)[],
403 ElementType (*)[]>::value,
406 :
storage_(other.data(), other.size())
409 ~span() noexcept = default;
412 operator=(const
span& other) noexcept = default;
415 template <
std::
size_t Count>
419 return {
data(), Count};
422 template <std::
size_t Count>
426 return {
data() + (
size() - Count), Count};
429 template <std::
size_t Offset, std::
size_t Count = dynamic_extent>
436 template <std::
size_t Offset, std::
size_t Count = dynamic_extent>
441 return {
data() + Offset,
464 return {
data() + offset,
485 return *(
data() + idx);
521 #ifdef TCB_SPAN_HAVE_DEDUCTION_GUIDES
524 template <
class T,
size_t N>
525 span(T (&)[N])->span<T, N>;
527 template <
class T,
size_t N>
528 span(std::array<T, N>&)->span<T, N>;
530 template <
class T,
size_t N>
531 span(
const std::array<T, N>&)->span<
const T, N>;
533 template <
class Container>
534 span(Container&)->span<
typename Container::value_type>;
536 template <
class Container>
537 span(
const Container&)->span<
const typename Container::value_type>;
539 #endif // TCB_HAVE_DEDUCTION_GUIDES
541 template <
typename ElementType, std::
size_t Extent>
542 constexpr span<ElementType, Extent>
548 template <
typename T, std::
size_t N>
554 template <
typename T, std::
size_t N>
560 template <
typename T, std::
size_t N>
567 template <
typename Container>
573 template <
typename Container>
574 constexpr span<const typename Container::value_type>
580 template <
typename ElementType, std::
size_t Extent>
582 :
sizeof(ElementType) *
Extent)>
589 class ElementType,
size_t Extent,
590 typename std::enable_if<!std::is_const<ElementType>::value,
int>
::type = 0>
592 :
sizeof(ElementType) *
Extent)>
598 template <std::
size_t N,
typename E, std::
size_t S>
615 #if defined(_MSC_VER)
616 #define TCB_SPAN_TUPLE_SIZE_KIND class
618 #define TCB_SPAN_TUPLE_SIZE_KIND struct
621 #if defined(__clang__)
622 #pragma clang diagnostic push
623 #pragma clang diagnostic ignored "-Wmismatched-tags"
626 template <
typename ElementType,
size_t Extent>
628 :
public integral_constant<size_t, Extent> {};
630 template <
typename ElementType>
634 template <
size_t I,
typename ElementType,
size_t Extent>
643 #if defined(__clang__)
644 #pragma clang diagnostic pop
647 #undef TCB_SPAN_TUPLE_SIZE_KIND
651 #endif // TCB_SPAN_HPP_INCLUDED
658 template <
typename A,
size_t E = tcb::dynamic_extent>