preCICE v3.1.1
Loading...
Searching...
No Matches
span.hpp
Go to the documentation of this file.
1// clang-format off
2/*
3This is an implementation of C++20's std::span
4http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf
5*/
6
7// Copyright Tristan Brindle 2018.
8// Distributed under the Boost Software License, Version 1.0.
9// (See accompanying file ../../LICENSE_1_0.txt or copy at
10// https://www.boost.org/LICENSE_1_0.txt)
11
12#ifndef PRECICE_SPAN_HPP_INCLUDED
13#define PRECICE_SPAN_HPP_INCLUDED
14
15#pragma once
16
17#include <array>
18#include <cstddef>
19#include <cstdint>
20#include <cstring>
21#include <type_traits>
22
23#ifndef PRECICE_SPAN_NO_EXCEPTIONS
24// Attempt to discover whether we're being compiled with exception support
25#if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND))
26#define PRECICE_SPAN_NO_EXCEPTIONS
27#endif
28#endif
29
30#ifndef PRECICE_SPAN_NO_EXCEPTIONS
31#include <cstdio>
32#include <stdexcept>
33#endif
34
35// Various feature test macros
36
37#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
38#define PRECICE_SPAN_HAVE_CPP17
39#endif
40
41#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
42#define PRECICE_SPAN_HAVE_CPP14
43#endif
44
45namespace precice {
46
47// Establish default contract checking behavior
48#if !defined(PRECICE_SPAN_THROW_ON_CONTRACT_VIOLATION) && \
49 !defined(PRECICE_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) && \
50 !defined(PRECICE_SPAN_NO_CONTRACT_CHECKING)
51#if defined(NDEBUG) || !defined(PRECICE_SPAN_HAVE_CPP14)
52#define PRECICE_SPAN_NO_CONTRACT_CHECKING
53#else
54#define PRECICE_SPAN_TERMINATE_ON_CONTRACT_VIOLATION
55#endif
56#endif
57
58#if defined(PRECICE_SPAN_THROW_ON_CONTRACT_VIOLATION)
59struct contract_violation_error : std::logic_error {
60 explicit contract_violation_error(const char* msg) : std::logic_error(msg)
61 {}
62};
63
64inline void contract_violation(const char* msg)
65{
66 throw contract_violation_error(msg);
67}
68
69#elif defined(PRECICE_SPAN_TERMINATE_ON_CONTRACT_VIOLATION)
70[[noreturn]] inline void contract_violation(const char* /*unused*/)
71{
73}
74#endif
75
76#if !defined(PRECICE_SPAN_NO_CONTRACT_CHECKING)
77#define PRECICE_SPAN_STRINGIFY(cond) #cond
78#define PRECICE_SPAN_EXPECT(cond) \
79 cond ? (void) 0 : contract_violation("Expected " PRECICE_SPAN_STRINGIFY(cond))
80#else
81#define PRECICE_SPAN_EXPECT(cond)
82#endif
83
84#if defined(PRECICE_SPAN_HAVE_CPP17) || defined(__cpp_inline_variables)
85#define PRECICE_SPAN_INLINE_VAR inline
86#else
87#define PRECICE_SPAN_INLINE_VAR
88#endif
89
90#if defined(PRECICE_SPAN_HAVE_CPP14) || \
91 (defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
92#define PRECICE_SPAN_HAVE_CPP14_CONSTEXPR
93#endif
94
95#if defined(PRECICE_SPAN_HAVE_CPP14_CONSTEXPR)
96#define PRECICE_SPAN_CONSTEXPR14 constexpr
97#else
98#define PRECICE_SPAN_CONSTEXPR14
99#endif
100
101#if defined(PRECICE_SPAN_HAVE_CPP14_CONSTEXPR) && \
102 (!defined(_MSC_VER) || _MSC_VER > 1900)
103#define PRECICE_SPAN_CONSTEXPR_ASSIGN constexpr
104#else
105#define PRECICE_SPAN_CONSTEXPR_ASSIGN
106#endif
107
108#if defined(PRECICE_SPAN_NO_CONTRACT_CHECKING)
109#define PRECICE_SPAN_CONSTEXPR11 constexpr
110#else
111#define PRECICE_SPAN_CONSTEXPR11 PRECICE_SPAN_CONSTEXPR14
112#endif
113
114#if defined(PRECICE_SPAN_HAVE_CPP17) || defined(__cpp_deduction_guides)
115#define PRECICE_SPAN_HAVE_DEDUCTION_GUIDES
116#endif
117
118#if defined(PRECICE_SPAN_HAVE_CPP17) || defined(__cpp_lib_byte)
119#define PRECICE_SPAN_HAVE_STD_BYTE
120#endif
121
122#if defined(PRECICE_SPAN_HAVE_CPP17) || defined(__cpp_lib_array_constexpr)
123#define PRECICE_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC
124#endif
125
126#if defined(PRECICE_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC)
127#define PRECICE_SPAN_ARRAY_CONSTEXPR constexpr
128#else
129#define PRECICE_SPAN_ARRAY_CONSTEXPR
130#endif
131
132#ifdef PRECICE_SPAN_HAVE_STD_BYTE
133using byte = std::byte;
134#else
135using byte = unsigned char;
136#endif
137
138#if defined(PRECICE_SPAN_HAVE_CPP17)
139#define PRECICE_SPAN_NODISCARD [[nodiscard]]
140#else
141#define PRECICE_SPAN_NODISCARD
142#endif
143
145
146template <typename ElementType, std::size_t Extent = dynamic_extent>
147class span;
148
149namespace detail {
150
151template <typename E, std::size_t S>
153 constexpr span_storage() noexcept = default;
154
155 constexpr span_storage(E* p_ptr, std::size_t /*unused*/) noexcept
156 : ptr(p_ptr)
157 {}
158
159 E* ptr = nullptr;
160 static constexpr std::size_t size = S;
161};
162
163template <typename E>
165 constexpr span_storage() noexcept = default;
166
167 constexpr span_storage(E* p_ptr, std::size_t p_size) noexcept
168 : ptr(p_ptr), size(p_size)
169 {}
170
171 E* ptr = nullptr;
173};
174
175// Reimplementation of C++17 std::size() and std::data()
176#if defined(PRECICE_SPAN_HAVE_CPP17) || \
177 defined(__cpp_lib_nonmember_container_access)
178using std::data;
179using std::size;
180#else
181template <class C>
182constexpr auto size(const C& c) -> decltype(c.size())
183{
184 return c.size();
185}
186
187template <class T, std::size_t N>
188constexpr std::size_t size(const T (&)[N]) noexcept
189{
190 return N;
191}
192
193template <class C>
194constexpr auto data(C& c) -> decltype(c.data())
195{
196 return c.data();
197}
198
199template <class C>
200constexpr auto data(const C& c) -> decltype(c.data())
201{
202 return c.data();
203}
204
205template <class T, std::size_t N>
206constexpr T* data(T (&array)[N]) noexcept
207{
208 return array;
209}
210
211template <class E>
212constexpr const E* data(std::initializer_list<E> il) noexcept
213{
214 return il.begin();
215}
216#endif // PRECICE_SPAN_HAVE_CPP17
217
218#if defined(PRECICE_SPAN_HAVE_CPP17) || defined(__cpp_lib_void_t)
219using std::void_t;
220#else
221template <typename...>
222using void_t = void;
223#endif
224
225template <typename T>
228
229template <typename>
231
232template <typename T, std::size_t S>
233struct is_span<span<T, S>> : std::true_type {};
234
235template <typename>
237
238template <typename T, std::size_t N>
239struct is_std_array<std::array<T, N>> : std::true_type {};
240
241template <typename, typename = void>
243
244template <typename T>
245struct has_size_and_data<T, void_t<decltype(detail::size(std::declval<T>())),
246 decltype(detail::data(std::declval<T>()))>>
247 : std::true_type {};
248
249template <typename C, typename U = uncvref_t<C>>
255
256template <typename T>
258
259template <typename, typename, typename = void>
261
262template <typename T, typename E>
264 T, E,
265 typename std::enable_if<
266 !std::is_same<
267 typename std::remove_cv<decltype(detail::data(std::declval<T>()))>::type,
268 void>::value &&
269 std::is_convertible<
270 remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
271 E (*)[]>::value
272 >::type>
273 : std::true_type {};
274
275template <typename, typename = size_t>
277
278template <typename T>
279struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
280
281} // namespace detail
282
283template <typename ElementType, std::size_t Extent>
284class span {
286 "A span's ElementType must be an object type (not a "
287 "reference type or void)");
289 "A span's ElementType must be a complete type (not a forward "
290 "declaration)");
292 "A span's ElementType cannot be an abstract class type");
293
295
296public:
297 // constants and types
298 using element_type = ElementType;
308
309 static constexpr size_type extent = Extent;
310
311 // [span.cons], span constructors, copy, assignment, and destructor
312 template <
313 std::size_t E = Extent,
314 typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0>
315 constexpr span() noexcept
316 {}
317
323
325 : storage_(first_elem, last_elem - first_elem)
326 {
328 last_elem - first_elem ==
329 static_cast<std::ptrdiff_t>(extent));
330 }
331
332 template <std::size_t N, std::size_t E = Extent,
333 typename std::enable_if<
334 (E == dynamic_extent || N == E) &&
336 element_type (&)[N], ElementType>::value,
337 int>::type = 0>
338 constexpr span(element_type (&arr)[N]) noexcept : storage_(arr, N)
339 {}
340
341 template <typename T, std::size_t N, std::size_t E = Extent,
342 typename std::enable_if<
343 (E == dynamic_extent || N == E) &&
345 std::array<T, N>&, ElementType>::value,
346 int>::type = 0>
348 : storage_(arr.data(), N)
349 {}
350
351 template <typename T, std::size_t N, std::size_t E = Extent,
352 typename std::enable_if<
353 (E == dynamic_extent || N == E) &&
355 const std::array<T, N>&, ElementType>::value,
356 int>::type = 0>
358 : storage_(arr.data(), N)
359 {}
360
361 template <
362 typename Container, std::size_t E = Extent,
363 typename std::enable_if<
366 Container&, ElementType>::value,
367 int>::type = 0>
368 constexpr span(Container& cont)
369 : storage_(detail::data(cont), detail::size(cont))
370 {}
371
372 template <
373 typename Container, std::size_t E = Extent,
374 typename std::enable_if<
377 const Container&, ElementType>::value,
378 int>::type = 0>
379 constexpr span(const Container& cont)
380 : storage_(detail::data(cont), detail::size(cont))
381 {}
382
383 constexpr span(const span& other) noexcept = default;
384
385 template <typename OtherElementType, std::size_t OtherExtent,
386 typename std::enable_if<
387 (Extent == dynamic_extent || OtherExtent == dynamic_extent ||
388 Extent == OtherExtent) &&
389 std::is_convertible<OtherElementType (*)[],
390 ElementType (*)[]>::value,
391 int>::type = 0>
392 constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
393 : storage_(other.data(), other.size())
394 {}
395
396 ~span() noexcept = default;
397
399 operator=(const span& other) noexcept = default;
400
401 // Custom span constructor to allow string_view imitation
402 template <
403 typename T,
404 std::size_t E = Extent,
405 typename std::enable_if<
406 E == dynamic_extent && (std::is_same<T, const char*>::value || std::is_same<T, char*>::value),
407 int>::type = 0>
408 span(T cstring)
409 : storage_(cstring, std::strlen(cstring))
410 {
412 }
413
414 // [span.sub], span subviews
415 template <std::size_t Count>
417 {
418 PRECICE_SPAN_EXPECT(Count <= size());
419 return {data(), Count};
420 }
421
422 template <std::size_t Count>
424 {
425 PRECICE_SPAN_EXPECT(Count <= size());
426 return {data() + (size() - Count), Count};
427 }
428
429 template <std::size_t Offset, std::size_t Count = dynamic_extent>
431 span<ElementType, Count != dynamic_extent
432 ? Count
433 : (Extent != dynamic_extent ? Extent - Offset
434 : dynamic_extent)>;
435
436 template <std::size_t Offset, std::size_t Count = dynamic_extent>
438 {
439 PRECICE_SPAN_EXPECT(Offset <= size() &&
440 (Count == dynamic_extent || Offset + Count <= size()));
441 return {data() + Offset,
442 Count != dynamic_extent ? Count : size() - Offset};
443 }
444
446 first(size_type count) const
447 {
448 PRECICE_SPAN_EXPECT(count <= size());
449 return {data(), count};
450 }
451
453 last(size_type count) const
454 {
455 PRECICE_SPAN_EXPECT(count <= size());
456 return {data() + (size() - count), count};
457 }
458
461 {
462 PRECICE_SPAN_EXPECT(offset <= size() &&
463 (count == dynamic_extent || offset + count <= size()));
464 return {data() + offset,
465 count == dynamic_extent ? size() - offset : count};
466 }
467
468 // [span.obs], span observers
469 constexpr size_type size() const noexcept { return storage_.size; }
470
471 constexpr size_type size_bytes() const noexcept
472 {
473 return size() * sizeof(element_type);
474 }
475
476 PRECICE_SPAN_NODISCARD constexpr bool empty() const noexcept
477 {
478 return size() == 0;
479 }
480
481 // [span.elem], span element access
483 {
484 PRECICE_SPAN_EXPECT(idx < size());
485 return *(data() + idx);
486 }
487
489 {
491 return *data();
492 }
493
495 {
497 return *(data() + (size() - 1));
498 }
499
500 constexpr pointer data() const noexcept { return storage_.ptr; }
501
502 // [span.iterators], span iterator support
503 constexpr iterator begin() const noexcept { return data(); }
504
505 constexpr iterator end() const noexcept { return data() + size(); }
506
508 {
509 return reverse_iterator(end());
510 }
511
513 {
514 return reverse_iterator(begin());
515 }
516
517private:
519};
520
521#ifdef PRECICE_SPAN_HAVE_DEDUCTION_GUIDES
522
523/* Deduction Guides */
524template <class T, size_t N>
525span(T (&)[N])->span<T, N>;
526
527template <class T, size_t N>
528span(std::array<T, N>&)->span<T, N>;
529
530template <class T, size_t N>
531span(const std::array<T, N>&)->span<const T, N>;
532
533template <class Container>
534span(Container&)->span<typename std::remove_reference<
535 decltype(*detail::data(std::declval<Container&>()))>::type>;
536
537template <class Container>
538span(const Container&)->span<const typename Container::value_type>;
539
540#endif // PRECICE_HAVE_DEDUCTION_GUIDES
541
542template <typename ElementType, std::size_t Extent>
543constexpr span<ElementType, Extent>
545{
546 return s;
547}
548
549template <typename T, std::size_t N>
550constexpr span<T, N> make_span(T (&arr)[N]) noexcept
551{
552 return {arr};
553}
554
555template <typename T, std::size_t N>
557{
558 return {arr};
559}
560
561template <typename T, std::size_t N>
562PRECICE_SPAN_ARRAY_CONSTEXPR span<const T, N>
563make_span(const std::array<T, N>& arr) noexcept
564{
565 return {arr};
566}
567
568template <typename Container>
569constexpr span<typename std::remove_reference<
570 decltype(*detail::data(std::declval<Container&>()))>::type>
571make_span(Container& cont)
572{
573 return {cont};
574}
575
576template <typename Container>
577constexpr span<const typename Container::value_type>
578make_span(const Container& cont)
579{
580 return {cont};
581}
582
583template <typename ElementType, std::size_t Extent>
584span<const byte, ((Extent == dynamic_extent) ? dynamic_extent
585 : sizeof(ElementType) * Extent)>
586as_bytes(span<ElementType, Extent> s) noexcept
587{
588 return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
589}
590
591template <
592 class ElementType, size_t Extent,
594span<byte, ((Extent == dynamic_extent) ? dynamic_extent
595 : sizeof(ElementType) * Extent)>
596as_writable_bytes(span<ElementType, Extent> s) noexcept
597{
598 return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
599}
600
601template <std::size_t N, typename E, std::size_t S>
602constexpr auto get(span<E, S> s) -> decltype(s[N])
603{
604 return s[N];
605}
606
607} // namespace precice
608
609namespace std {
610
611template <typename ElementType, size_t Extent>
612class tuple_size<precice::span<ElementType, Extent>>
613 : public integral_constant<size_t, Extent> {};
614
615template <typename ElementType>
616class tuple_size<precice::span<
617 ElementType, precice::dynamic_extent>>; // not defined
618
619template <size_t I, typename ElementType, size_t Extent>
620class tuple_element<I, precice::span<ElementType, Extent>> {
621public:
622 static_assert(Extent != precice::dynamic_extent &&
623 I < Extent,
624 "");
625 using type = ElementType;
626};
627
628} // end namespace std
629
630#endif // PRECICE_SPAN_HPP_INCLUDED
double const * ptr
Definition ExportCSV.cpp:23
A C++ 11 implementation of the non-owning C++20 std::span type.
Definition span.hpp:284
PRECICE_SPAN_CONSTEXPR11 reference front() const
Definition span.hpp:488
PRECICE_SPAN_CONSTEXPR11 span< element_type, dynamic_extent > subspan(size_type offset, size_type count=dynamic_extent) const
Definition span.hpp:460
PRECICE_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin() const noexcept
Definition span.hpp:507
std::reverse_iterator< iterator > reverse_iterator
Definition span.hpp:307
PRECICE_SPAN_CONSTEXPR11 span< element_type, dynamic_extent > first(size_type count) const
Definition span.hpp:446
constexpr pointer data() const noexcept
Definition span.hpp:500
constexpr span(const span &other) noexcept=default
typename std::remove_cv< ElementType >::type value_type
Definition span.hpp:299
pointer iterator
Definition span.hpp:306
PRECICE_SPAN_ARRAY_CONSTEXPR span(const std::array< T, N > &arr) noexcept
Definition span.hpp:357
constexpr span(Container &cont)
Definition span.hpp:368
PRECICE_SPAN_CONSTEXPR11 span< element_type, Count > first() const
Definition span.hpp:416
PRECICE_SPAN_NODISCARD constexpr bool empty() const noexcept
Definition span.hpp:476
PRECICE_SPAN_CONSTEXPR11 span< element_type, Count > last() const
Definition span.hpp:423
static constexpr size_type extent
Definition span.hpp:309
PRECICE_SPAN_ARRAY_CONSTEXPR reverse_iterator rend() const noexcept
Definition span.hpp:512
constexpr span(element_type(&arr)[N]) noexcept
Definition span.hpp:338
PRECICE_SPAN_CONSTEXPR11 reference operator[](size_type idx) const
Definition span.hpp:482
ElementType element_type
Definition span.hpp:298
constexpr iterator begin() const noexcept
Definition span.hpp:503
storage_type storage_
Definition span.hpp:518
constexpr iterator end() const noexcept
Definition span.hpp:505
const element_type & const_reference
Definition span.hpp:305
constexpr span(const span< OtherElementType, OtherExtent > &other) noexcept
Definition span.hpp:392
element_type & reference
Definition span.hpp:304
const element_type * const_pointer
Definition span.hpp:303
PRECICE_SPAN_CONSTEXPR11 subspan_return_t< Offset, Count > subspan() const
Definition span.hpp:437
constexpr span(const Container &cont)
Definition span.hpp:379
PRECICE_SPAN_CONSTEXPR11 span(pointer ptr, size_type count)
Definition span.hpp:318
constexpr size_type size_bytes() const noexcept
Definition span.hpp:471
PRECICE_SPAN_CONSTEXPR11 span(pointer first_elem, pointer last_elem)
Definition span.hpp:324
element_type * pointer
Definition span.hpp:302
constexpr size_type size() const noexcept
Definition span.hpp:469
constexpr span() noexcept
Definition span.hpp:315
~span() noexcept=default
PRECICE_SPAN_ARRAY_CONSTEXPR span(std::array< T, N > &arr) noexcept
Definition span.hpp:347
PRECICE_SPAN_CONSTEXPR11 span< element_type, dynamic_extent > last(size_type count) const
Definition span.hpp:453
PRECICE_SPAN_CONSTEXPR11 reference back() const
Definition span.hpp:494
T data(T... args)
typename std::remove_pointer< T >::type remove_pointer_t
Definition span.hpp:257
constexpr auto size(const C &c) -> decltype(c.size())
Definition span.hpp:182
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition span.hpp:226
constexpr auto data(C &c) -> decltype(c.data())
Definition span.hpp:194
Main namespace of the precice library.
span< byte,((Extent==dynamic_extent) ? dynamic_extent :sizeof(ElementType) *Extent)> as_writable_bytes(span< ElementType, Extent > s) noexcept
Definition span.hpp:596
span< const byte,((Extent==dynamic_extent) ? dynamic_extent :sizeof(ElementType) *Extent)> as_bytes(span< ElementType, Extent > s) noexcept
Definition span.hpp:586
constexpr span< ElementType, Extent > make_span(span< ElementType, Extent > s) noexcept
Definition span.hpp:544
constexpr auto get(span< E, S > s) -> decltype(s[N])
Definition span.hpp:602
PRECICE_SPAN_INLINE_VAR constexpr std::size_t dynamic_extent
Definition span.hpp:144
unsigned char byte
Definition span.hpp:135
STL namespace.
T size(T... args)
#define PRECICE_SPAN_NODISCARD
Definition span.hpp:141
#define PRECICE_SPAN_CONSTEXPR11
Definition span.hpp:109
#define PRECICE_SPAN_INLINE_VAR
Definition span.hpp:87
#define PRECICE_SPAN_ARRAY_CONSTEXPR
Definition span.hpp:129
#define PRECICE_SPAN_EXPECT(cond)
Definition span.hpp:81
#define PRECICE_SPAN_CONSTEXPR_ASSIGN
Definition span.hpp:105
static constexpr bool value
Definition span.hpp:251
constexpr span_storage() noexcept=default
static constexpr std::size_t size
Definition span.hpp:160
T terminate(T... args)