1 /*
2 * Copyright 2017 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef FLATBUFFERS_STL_EMULATION_H_
18 #define FLATBUFFERS_STL_EMULATION_H_
19
20 // clang-format off
21 #include "flatbuffers/base.h"
22
23 #include <string>
24 #include <type_traits>
25 #include <vector>
26 #include <memory>
27 #include <limits>
28
29 #if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
30 #define FLATBUFFERS_CPP98_STL
31 #endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
32
33 #if defined(FLATBUFFERS_CPP98_STL)
34 #include <cctype>
35 #endif // defined(FLATBUFFERS_CPP98_STL)
36
37 // Detect C++17 compatible compiler.
38 // __cplusplus >= 201703L - a compiler has support of 'static inline' variables.
39 #if defined(FLATBUFFERS_USE_STD_OPTIONAL) \
40 || (defined(__cplusplus) && __cplusplus >= 201703L) \
41 || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))
42 #include <optional>
43 #ifndef FLATBUFFERS_USE_STD_OPTIONAL
44 #define FLATBUFFERS_USE_STD_OPTIONAL
45 #endif
46 #endif // defined(FLATBUFFERS_USE_STD_OPTIONAL) ...
47
48 // The __cpp_lib_span is the predefined feature macro.
49 #if defined(FLATBUFFERS_USE_STD_SPAN)
50 #include <span>
51 #elif defined(__cpp_lib_span) && defined(__has_include)
52 #if __has_include(<span>)
53 #include <span>
54 #define FLATBUFFERS_USE_STD_SPAN
55 #endif
56 #else
57 // Disable non-trivial ctors if FLATBUFFERS_SPAN_MINIMAL defined.
58 #if !defined(FLATBUFFERS_TEMPLATES_ALIASES) || defined(FLATBUFFERS_CPP98_STL)
59 #define FLATBUFFERS_SPAN_MINIMAL
60 #else
61 // Enable implicit construction of a span<T,N> from a std::array<T,N>.
62 #include <array>
63 #endif
64 #endif // defined(FLATBUFFERS_USE_STD_SPAN)
65
66 // This header provides backwards compatibility for C++98 STLs like stlport.
67 namespace flatbuffers {
68
69 // Retrieve ::back() from a string in a way that is compatible with pre C++11
70 // STLs (e.g stlport).
string_back(std::string & value)71 inline char& string_back(std::string &value) {
72 return value[value.length() - 1];
73 }
74
string_back(const std::string & value)75 inline char string_back(const std::string &value) {
76 return value[value.length() - 1];
77 }
78
79 // Helper method that retrieves ::data() from a vector in a way that is
80 // compatible with pre C++11 STLs (e.g stlport).
vector_data(std::vector<T> & vector)81 template <typename T> inline T *vector_data(std::vector<T> &vector) {
82 // In some debug environments, operator[] does bounds checking, so &vector[0]
83 // can't be used.
84 return vector.empty() ? nullptr : &vector[0];
85 }
86
vector_data(const std::vector<T> & vector)87 template <typename T> inline const T *vector_data(
88 const std::vector<T> &vector) {
89 return vector.empty() ? nullptr : &vector[0];
90 }
91
92 template <typename T, typename V>
vector_emplace_back(std::vector<T> * vector,V && data)93 inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
94 #if defined(FLATBUFFERS_CPP98_STL)
95 vector->push_back(data);
96 #else
97 vector->emplace_back(std::forward<V>(data));
98 #endif // defined(FLATBUFFERS_CPP98_STL)
99 }
100
101 #ifndef FLATBUFFERS_CPP98_STL
102 #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
103 template <typename T>
104 using numeric_limits = std::numeric_limits<T>;
105 #else
106 template <typename T> class numeric_limits :
107 public std::numeric_limits<T> {};
108 #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
109 #else
110 template <typename T> class numeric_limits :
111 public std::numeric_limits<T> {
112 public:
113 // Android NDK fix.
lowest()114 static T lowest() {
115 return std::numeric_limits<T>::min();
116 }
117 };
118
119 template <> class numeric_limits<float> :
120 public std::numeric_limits<float> {
121 public:
lowest()122 static float lowest() { return -FLT_MAX; }
123 };
124
125 template <> class numeric_limits<double> :
126 public std::numeric_limits<double> {
127 public:
lowest()128 static double lowest() { return -DBL_MAX; }
129 };
130
131 template <> class numeric_limits<unsigned long long> {
132 public:
min()133 static unsigned long long min() { return 0ULL; }
max()134 static unsigned long long max() { return ~0ULL; }
lowest()135 static unsigned long long lowest() {
136 return numeric_limits<unsigned long long>::min();
137 }
138 };
139
140 template <> class numeric_limits<long long> {
141 public:
min()142 static long long min() {
143 return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1));
144 }
max()145 static long long max() {
146 return static_cast<long long>(
147 (1ULL << ((sizeof(long long) << 3) - 1)) - 1);
148 }
lowest()149 static long long lowest() {
150 return numeric_limits<long long>::min();
151 }
152 };
153 #endif // FLATBUFFERS_CPP98_STL
154
155 #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
156 #ifndef FLATBUFFERS_CPP98_STL
157 template <typename T> using is_scalar = std::is_scalar<T>;
158 template <typename T, typename U> using is_same = std::is_same<T,U>;
159 template <typename T> using is_floating_point = std::is_floating_point<T>;
160 template <typename T> using is_unsigned = std::is_unsigned<T>;
161 template <typename T> using is_enum = std::is_enum<T>;
162 template <typename T> using make_unsigned = std::make_unsigned<T>;
163 template<bool B, class T, class F>
164 using conditional = std::conditional<B, T, F>;
165 template<class T, T v>
166 using integral_constant = std::integral_constant<T, v>;
167 template <bool B>
168 using bool_constant = integral_constant<bool, B>;
169 #else
170 // Map C++ TR1 templates defined by stlport.
171 template <typename T> using is_scalar = std::tr1::is_scalar<T>;
172 template <typename T, typename U> using is_same = std::tr1::is_same<T,U>;
173 template <typename T> using is_floating_point =
174 std::tr1::is_floating_point<T>;
175 template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
176 template <typename T> using is_enum = std::tr1::is_enum<T>;
177 // Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned.
178 template<typename T> struct make_unsigned {
179 static_assert(is_unsigned<T>::value, "Specialization not implemented!");
180 using type = T;
181 };
182 template<> struct make_unsigned<char> { using type = unsigned char; };
183 template<> struct make_unsigned<short> { using type = unsigned short; };
184 template<> struct make_unsigned<int> { using type = unsigned int; };
185 template<> struct make_unsigned<long> { using type = unsigned long; };
186 template<>
187 struct make_unsigned<long long> { using type = unsigned long long; };
188 template<bool B, class T, class F>
189 using conditional = std::tr1::conditional<B, T, F>;
190 template<class T, T v>
191 using integral_constant = std::tr1::integral_constant<T, v>;
192 template <bool B>
193 using bool_constant = integral_constant<bool, B>;
194 #endif // !FLATBUFFERS_CPP98_STL
195 #else
196 // MSVC 2010 doesn't support C++11 aliases.
197 template <typename T> struct is_scalar : public std::is_scalar<T> {};
198 template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
199 template <typename T> struct is_floating_point :
200 public std::is_floating_point<T> {};
201 template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
202 template <typename T> struct is_enum : public std::is_enum<T> {};
203 template <typename T> struct make_unsigned : public std::make_unsigned<T> {};
204 template<bool B, class T, class F>
205 struct conditional : public std::conditional<B, T, F> {};
206 template<class T, T v>
207 struct integral_constant : public std::integral_constant<T, v> {};
208 template <bool B>
209 struct bool_constant : public integral_constant<bool, B> {};
210 #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
211
212 #ifndef FLATBUFFERS_CPP98_STL
213 #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
214 template <class T> using unique_ptr = std::unique_ptr<T>;
215 #else
216 // MSVC 2010 doesn't support C++11 aliases.
217 // We're manually "aliasing" the class here as we want to bring unique_ptr
218 // into the flatbuffers namespace. We have unique_ptr in the flatbuffers
219 // namespace we have a completely independent implementation (see below)
220 // for C++98 STL implementations.
221 template <class T> class unique_ptr : public std::unique_ptr<T> {
222 public:
223 unique_ptr() {}
224 explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
225 unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
226 unique_ptr(unique_ptr&& u) { *this = std::move(u); }
227 unique_ptr& operator=(std::unique_ptr<T>&& u) {
228 std::unique_ptr<T>::reset(u.release());
229 return *this;
230 }
231 unique_ptr& operator=(unique_ptr&& u) {
232 std::unique_ptr<T>::reset(u.release());
233 return *this;
234 }
235 unique_ptr& operator=(T* p) {
236 return std::unique_ptr<T>::operator=(p);
237 }
238 };
239 #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
240 #else
241 // Very limited implementation of unique_ptr.
242 // This is provided simply to allow the C++ code generated from the default
243 // settings to function in C++98 environments with no modifications.
244 template <class T> class unique_ptr {
245 public:
246 typedef T element_type;
247
248 unique_ptr() : ptr_(nullptr) {}
249 explicit unique_ptr(T* p) : ptr_(p) {}
250 unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); }
251 unique_ptr(const unique_ptr& u) : ptr_(nullptr) {
252 reset(const_cast<unique_ptr*>(&u)->release());
253 }
254 ~unique_ptr() { reset(); }
255
256 unique_ptr& operator=(const unique_ptr& u) {
257 reset(const_cast<unique_ptr*>(&u)->release());
258 return *this;
259 }
260
261 unique_ptr& operator=(unique_ptr&& u) {
262 reset(u.release());
263 return *this;
264 }
265
266 unique_ptr& operator=(T* p) {
267 reset(p);
268 return *this;
269 }
270
271 const T& operator*() const { return *ptr_; }
272 T* operator->() const { return ptr_; }
273 T* get() const noexcept { return ptr_; }
274 explicit operator bool() const { return ptr_ != nullptr; }
275
276 // modifiers
277 T* release() {
278 T* value = ptr_;
279 ptr_ = nullptr;
280 return value;
281 }
282
283 void reset(T* p = nullptr) {
284 T* value = ptr_;
285 ptr_ = p;
286 if (value) delete value;
287 }
288
289 void swap(unique_ptr& u) {
290 T* temp_ptr = ptr_;
291 ptr_ = u.ptr_;
292 u.ptr_ = temp_ptr;
293 }
294
295 private:
296 T* ptr_;
297 };
298
299 template <class T> bool operator==(const unique_ptr<T>& x,
300 const unique_ptr<T>& y) {
301 return x.get() == y.get();
302 }
303
304 template <class T, class D> bool operator==(const unique_ptr<T>& x,
305 const D* y) {
306 return static_cast<D*>(x.get()) == y;
307 }
308
309 template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
310 return reinterpret_cast<intptr_t>(x.get()) == y;
311 }
312
313 template <class T> bool operator!=(const unique_ptr<T>& x, decltype(nullptr)) {
314 return !!x;
315 }
316
317 template <class T> bool operator!=(decltype(nullptr), const unique_ptr<T>& x) {
318 return !!x;
319 }
320
321 template <class T> bool operator==(const unique_ptr<T>& x, decltype(nullptr)) {
322 return !x;
323 }
324
325 template <class T> bool operator==(decltype(nullptr), const unique_ptr<T>& x) {
326 return !x;
327 }
328
329 #endif // !FLATBUFFERS_CPP98_STL
330
331 #ifdef FLATBUFFERS_USE_STD_OPTIONAL
332 template<class T>
333 using Optional = std::optional<T>;
334 using nullopt_t = std::nullopt_t;
335 inline constexpr nullopt_t nullopt = std::nullopt;
336
337 #else
338 // Limited implementation of Optional<T> type for a scalar T.
339 // This implementation limited by trivial types compatible with
340 // std::is_arithmetic<T> or std::is_enum<T> type traits.
341
342 // A tag to indicate an empty flatbuffers::optional<T>.
343 struct nullopt_t {
344 explicit FLATBUFFERS_CONSTEXPR_CPP11 nullopt_t(int) {}
345 };
346
347 #if defined(FLATBUFFERS_CONSTEXPR_DEFINED)
348 namespace internal {
349 template <class> struct nullopt_holder {
350 static constexpr nullopt_t instance_ = nullopt_t(0);
351 };
352 template<class Dummy>
353 constexpr nullopt_t nullopt_holder<Dummy>::instance_;
354 }
355 static constexpr const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
356
357 #else
358 namespace internal {
359 template <class> struct nullopt_holder {
360 static const nullopt_t instance_;
361 };
362 template<class Dummy>
363 const nullopt_t nullopt_holder<Dummy>::instance_ = nullopt_t(0);
364 }
365 static const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
366
367 #endif
368
369 template<class T>
370 class Optional FLATBUFFERS_FINAL_CLASS {
371 // Non-scalar 'T' would extremely complicated Optional<T>.
372 // Use is_scalar<T> checking because flatbuffers flatbuffers::is_arithmetic<T>
373 // isn't implemented.
374 static_assert(flatbuffers::is_scalar<T>::value, "unexpected type T");
375
376 public:
377 ~Optional() {}
378
379 FLATBUFFERS_CONSTEXPR_CPP11 Optional() FLATBUFFERS_NOEXCEPT
380 : value_(), has_value_(false) {}
381
382 FLATBUFFERS_CONSTEXPR_CPP11 Optional(nullopt_t) FLATBUFFERS_NOEXCEPT
383 : value_(), has_value_(false) {}
384
385 FLATBUFFERS_CONSTEXPR_CPP11 Optional(T val) FLATBUFFERS_NOEXCEPT
386 : value_(val), has_value_(true) {}
387
388 FLATBUFFERS_CONSTEXPR_CPP11 Optional(const Optional &other) FLATBUFFERS_NOEXCEPT
389 : value_(other.value_), has_value_(other.has_value_) {}
390
391 FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(const Optional &other) FLATBUFFERS_NOEXCEPT {
392 value_ = other.value_;
393 has_value_ = other.has_value_;
394 return *this;
395 }
396
397 FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(nullopt_t) FLATBUFFERS_NOEXCEPT {
398 value_ = T();
399 has_value_ = false;
400 return *this;
401 }
402
403 FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(T val) FLATBUFFERS_NOEXCEPT {
404 value_ = val;
405 has_value_ = true;
406 return *this;
407 }
408
409 void reset() FLATBUFFERS_NOEXCEPT {
410 *this = nullopt;
411 }
412
413 void swap(Optional &other) FLATBUFFERS_NOEXCEPT {
414 std::swap(value_, other.value_);
415 std::swap(has_value_, other.has_value_);
416 }
417
418 FLATBUFFERS_CONSTEXPR_CPP11 FLATBUFFERS_EXPLICIT_CPP11 operator bool() const FLATBUFFERS_NOEXCEPT {
419 return has_value_;
420 }
421
422 FLATBUFFERS_CONSTEXPR_CPP11 bool has_value() const FLATBUFFERS_NOEXCEPT {
423 return has_value_;
424 }
425
426 FLATBUFFERS_CONSTEXPR_CPP11 const T& operator*() const FLATBUFFERS_NOEXCEPT {
427 return value_;
428 }
429
430 const T& value() const {
431 FLATBUFFERS_ASSERT(has_value());
432 return value_;
433 }
434
435 T value_or(T default_value) const FLATBUFFERS_NOEXCEPT {
436 return has_value() ? value_ : default_value;
437 }
438
439 private:
440 T value_;
441 bool has_value_;
442 };
443
444 template<class T>
445 FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& opt, nullopt_t) FLATBUFFERS_NOEXCEPT {
446 return !opt;
447 }
448 template<class T>
449 FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(nullopt_t, const Optional<T>& opt) FLATBUFFERS_NOEXCEPT {
450 return !opt;
451 }
452
453 template<class T, class U>
454 FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const U& rhs) FLATBUFFERS_NOEXCEPT {
455 return static_cast<bool>(lhs) && (*lhs == rhs);
456 }
457
458 template<class T, class U>
459 FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const T& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
460 return static_cast<bool>(rhs) && (lhs == *rhs);
461 }
462
463 template<class T, class U>
464 FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
465 return static_cast<bool>(lhs) != static_cast<bool>(rhs)
466 ? false
467 : !static_cast<bool>(lhs) ? false : (*lhs == *rhs);
468 }
469 #endif // FLATBUFFERS_USE_STD_OPTIONAL
470
471
472 // Very limited and naive partial implementation of C++20 std::span<T,Extent>.
473 #if defined(FLATBUFFERS_USE_STD_SPAN)
474 inline constexpr std::size_t dynamic_extent = std::dynamic_extent;
475 template<class T, std::size_t Extent = std::dynamic_extent>
476 using span = std::span<T, Extent>;
477
478 #else // !defined(FLATBUFFERS_USE_STD_SPAN)
479 FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast<std::size_t>(-1);
480
481 // Exclude this code if MSVC2010 or non-STL Android is active.
482 // The non-STL Android doesn't have `std::is_convertible` required for SFINAE.
483 #if !defined(FLATBUFFERS_SPAN_MINIMAL)
484 namespace internal {
485 // This is SFINAE helper class for checking of a common condition:
486 // > This overload only participates in overload resolution
487 // > Check whether a pointer to an array of U can be converted
488 // > to a pointer to an array of E.
489 // This helper is used for checking of 'U -> const U'.
490 template<class E, std::size_t Extent, class U, std::size_t N>
491 struct is_span_convertable {
492 using type =
493 typename std::conditional<std::is_convertible<U (*)[], E (*)[]>::value
494 && (Extent == dynamic_extent || N == Extent),
495 int, void>::type;
496 };
497
498 } // namespace internal
499 #endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
500
501 // T - element type; must be a complete type that is not an abstract
502 // class type.
503 // Extent - the number of elements in the sequence, or dynamic.
504 template<class T, std::size_t Extent = dynamic_extent>
505 class span FLATBUFFERS_FINAL_CLASS {
506 public:
507 typedef T element_type;
508 typedef T& reference;
509 typedef const T& const_reference;
510 typedef T* pointer;
511 typedef const T* const_pointer;
512 typedef std::size_t size_type;
513
514 static FLATBUFFERS_CONSTEXPR size_type extent = Extent;
515
516 // Returns the number of elements in the span.
517 FLATBUFFERS_CONSTEXPR_CPP11 size_type size() const FLATBUFFERS_NOEXCEPT {
518 return count_;
519 }
520
521 // Returns the size of the sequence in bytes.
522 FLATBUFFERS_CONSTEXPR_CPP11
523 size_type size_bytes() const FLATBUFFERS_NOEXCEPT {
524 return size() * sizeof(element_type);
525 }
526
527 // Checks if the span is empty.
528 FLATBUFFERS_CONSTEXPR_CPP11 bool empty() const FLATBUFFERS_NOEXCEPT {
529 return size() == 0;
530 }
531
532 // Returns a pointer to the beginning of the sequence.
533 FLATBUFFERS_CONSTEXPR_CPP11 pointer data() const FLATBUFFERS_NOEXCEPT {
534 return data_;
535 }
536
537 // Returns a reference to the idx-th element of the sequence.
538 // The behavior is undefined if the idx is greater than or equal to size().
539 FLATBUFFERS_CONSTEXPR_CPP11 reference operator[](size_type idx) const {
540 return data()[idx];
541 }
542
543 FLATBUFFERS_CONSTEXPR_CPP11 span(const span &other) FLATBUFFERS_NOEXCEPT
544 : data_(other.data_), count_(other.count_) {}
545
546 FLATBUFFERS_CONSTEXPR_CPP14 span &operator=(const span &other)
547 FLATBUFFERS_NOEXCEPT {
548 data_ = other.data_;
549 count_ = other.count_;
550 }
551
552 // Limited implementation of
553 // `template <class It> constexpr std::span(It first, size_type count);`.
554 //
555 // Constructs a span that is a view over the range [first, first + count);
556 // the resulting span has: data() == first and size() == count.
557 // The behavior is undefined if [first, first + count) is not a valid range,
558 // or if (extent != flatbuffers::dynamic_extent && count != extent).
559 FLATBUFFERS_CONSTEXPR_CPP11
560 explicit span(pointer first, size_type count) FLATBUFFERS_NOEXCEPT
561 : data_ (Extent == dynamic_extent ? first : (Extent == count ? first : nullptr)),
562 count_(Extent == dynamic_extent ? count : (Extent == count ? Extent : 0)) {
563 // Make span empty if the count argument is incompatible with span<T,N>.
564 }
565
566 // Exclude this code if MSVC2010 is active. The MSVC2010 isn't C++11
567 // compliant, it doesn't support default template arguments for functions.
568 #if defined(FLATBUFFERS_SPAN_MINIMAL)
569 FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
570 count_(0) {
571 static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
572 }
573
574 #else
575 // Constructs an empty span whose data() == nullptr and size() == 0.
576 // This overload only participates in overload resolution if
577 // extent == 0 || extent == flatbuffers::dynamic_extent.
578 // A dummy template argument N is need dependency for SFINAE.
579 template<std::size_t N = 0,
580 typename internal::is_span_convertable<element_type, Extent, element_type, (N - N)>::type = 0>
581 FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
582 count_(0) {
583 static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
584 }
585
586 // Constructs a span that is a view over the array arr; the resulting span
587 // has size() == N and data() == std::data(arr). These overloads only
588 // participate in overload resolution if
589 // extent == std::dynamic_extent || N == extent is true and
590 // std::remove_pointer_t<decltype(std::data(arr))>(*)[]
591 // is convertible to element_type (*)[].
592 template<std::size_t N,
593 typename internal::is_span_convertable<element_type, Extent, element_type, N>::type = 0>
594 FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT
595 : data_(arr), count_(N) {}
596
597 template<class U, std::size_t N,
598 typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
599 FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
600 : data_(arr.data()), count_(N) {}
601
602 //template<class U, std::size_t N,
603 // int = 0>
604 //FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
605 // : data_(arr.data()), count_(N) {}
606
607 template<class U, std::size_t N,
608 typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
609 FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
610 : data_(arr.data()), count_(N) {}
611
612 // Converting constructor from another span s;
613 // the resulting span has size() == s.size() and data() == s.data().
614 // This overload only participates in overload resolution
615 // if extent == std::dynamic_extent || N == extent is true and U (*)[]
616 // is convertible to element_type (*)[].
617 template<class U, std::size_t N,
618 typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
619 FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span<U, N> &s) FLATBUFFERS_NOEXCEPT
620 : span(s.data(), s.size()) {
621 }
622
623 #endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
624
625 private:
626 // This is a naive implementation with 'count_' member even if (Extent != dynamic_extent).
627 pointer const data_;
628 const size_type count_;
629 };
630
631 #if !defined(FLATBUFFERS_SPAN_MINIMAL)
632 template<class U, std::size_t N>
633 FLATBUFFERS_CONSTEXPR_CPP11
634 flatbuffers::span<U, N> make_span(U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
635 return span<U, N>(arr);
636 }
637
638 template<class U, std::size_t N>
639 FLATBUFFERS_CONSTEXPR_CPP11
640 flatbuffers::span<const U, N> make_span(const U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
641 return span<const U, N>(arr);
642 }
643
644 template<class U, std::size_t N>
645 FLATBUFFERS_CONSTEXPR_CPP11
646 flatbuffers::span<U, N> make_span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
647 return span<U, N>(arr);
648 }
649
650 template<class U, std::size_t N>
651 FLATBUFFERS_CONSTEXPR_CPP11
652 flatbuffers::span<const U, N> make_span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
653 return span<const U, N>(arr);
654 }
655
656 template<class U, std::size_t N>
657 FLATBUFFERS_CONSTEXPR_CPP11
658 flatbuffers::span<U, dynamic_extent> make_span(U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
659 return span<U, dynamic_extent>(first, count);
660 }
661
662 template<class U, std::size_t N>
663 FLATBUFFERS_CONSTEXPR_CPP11
664 flatbuffers::span<const U, dynamic_extent> make_span(const U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
665 return span<const U, dynamic_extent>(first, count);
666 }
667 #endif
668
669 #endif // defined(FLATBUFFERS_USE_STD_SPAN)
670
671 } // namespace flatbuffers
672
673 #endif // FLATBUFFERS_STL_EMULATION_H_
674