blob: 66bd620d231a1261a66d7dc01d3188b535d4552f [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001/*
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
Austin Schuh272c6132020-11-14 16:37:52 -080021#include "flatbuffers/base.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -070022
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
Austin Schuh272c6132020-11-14 16:37:52 -080037// 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)
Austin Schuhe89fa2d2019-08-14 20:24:23 -070065
66// This header provides backwards compatibility for C++98 STLs like stlport.
67namespace flatbuffers {
68
69// Retrieve ::back() from a string in a way that is compatible with pre C++11
70// STLs (e.g stlport).
71inline char& string_back(std::string &value) {
72 return value[value.length() - 1];
73}
74
75inline 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).
81template <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
87template <typename T> inline const T *vector_data(
88 const std::vector<T> &vector) {
89 return vector.empty() ? nullptr : &vector[0];
90}
91
92template <typename T, typename V>
93inline 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.
114 static T lowest() {
115 return std::numeric_limits<T>::min();
116 }
117 };
118
Austin Schuh272c6132020-11-14 16:37:52 -0800119 template <> class numeric_limits<float> :
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700120 public std::numeric_limits<float> {
121 public:
122 static float lowest() { return -FLT_MAX; }
123 };
124
Austin Schuh272c6132020-11-14 16:37:52 -0800125 template <> class numeric_limits<double> :
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700126 public std::numeric_limits<double> {
127 public:
128 static double lowest() { return -DBL_MAX; }
129 };
130
131 template <> class numeric_limits<unsigned long long> {
132 public:
133 static unsigned long long min() { return 0ULL; }
134 static unsigned long long max() { return ~0ULL; }
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:
142 static long long min() {
143 return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1));
144 }
145 static long long max() {
146 return static_cast<long long>(
147 (1ULL << ((sizeof(long long) << 3) - 1)) - 1);
148 }
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>;
Austin Schuh272c6132020-11-14 16:37:52 -0800161 template <typename T> using is_enum = std::is_enum<T>;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700162 template <typename T> using make_unsigned = std::make_unsigned<T>;
Austin Schuh272c6132020-11-14 16:37:52 -0800163 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>;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700167 #else
168 // Map C++ TR1 templates defined by stlport.
169 template <typename T> using is_scalar = std::tr1::is_scalar<T>;
170 template <typename T, typename U> using is_same = std::tr1::is_same<T,U>;
171 template <typename T> using is_floating_point =
172 std::tr1::is_floating_point<T>;
173 template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
Austin Schuh272c6132020-11-14 16:37:52 -0800174 template <typename T> using is_enum = std::tr1::is_enum<T>;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700175 // Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned.
176 template<typename T> struct make_unsigned {
177 static_assert(is_unsigned<T>::value, "Specialization not implemented!");
178 using type = T;
179 };
180 template<> struct make_unsigned<char> { using type = unsigned char; };
181 template<> struct make_unsigned<short> { using type = unsigned short; };
182 template<> struct make_unsigned<int> { using type = unsigned int; };
183 template<> struct make_unsigned<long> { using type = unsigned long; };
184 template<>
185 struct make_unsigned<long long> { using type = unsigned long long; };
Austin Schuh272c6132020-11-14 16:37:52 -0800186 template<bool B, class T, class F>
187 using conditional = std::tr1::conditional<B, T, F>;
188 template<class T, T v>
189 using integral_constant = std::tr1::integral_constant<T, v>;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700190 #endif // !FLATBUFFERS_CPP98_STL
191#else
192 // MSVC 2010 doesn't support C++11 aliases.
193 template <typename T> struct is_scalar : public std::is_scalar<T> {};
194 template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
195 template <typename T> struct is_floating_point :
196 public std::is_floating_point<T> {};
197 template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
Austin Schuh272c6132020-11-14 16:37:52 -0800198 template <typename T> struct is_enum : public std::is_enum<T> {};
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700199 template <typename T> struct make_unsigned : public std::make_unsigned<T> {};
Austin Schuh272c6132020-11-14 16:37:52 -0800200 template<bool B, class T, class F>
201 struct conditional : public std::conditional<B, T, F> {};
202 template<class T, T v>
203 struct integral_constant : public std::integral_constant<T, v> {};
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700204#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
205
206#ifndef FLATBUFFERS_CPP98_STL
207 #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
208 template <class T> using unique_ptr = std::unique_ptr<T>;
209 #else
210 // MSVC 2010 doesn't support C++11 aliases.
211 // We're manually "aliasing" the class here as we want to bring unique_ptr
212 // into the flatbuffers namespace. We have unique_ptr in the flatbuffers
Austin Schuh272c6132020-11-14 16:37:52 -0800213 // namespace we have a completely independent implementation (see below)
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700214 // for C++98 STL implementations.
215 template <class T> class unique_ptr : public std::unique_ptr<T> {
216 public:
217 unique_ptr() {}
218 explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
219 unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
220 unique_ptr(unique_ptr&& u) { *this = std::move(u); }
221 unique_ptr& operator=(std::unique_ptr<T>&& u) {
222 std::unique_ptr<T>::reset(u.release());
223 return *this;
224 }
225 unique_ptr& operator=(unique_ptr&& u) {
226 std::unique_ptr<T>::reset(u.release());
227 return *this;
228 }
229 unique_ptr& operator=(T* p) {
230 return std::unique_ptr<T>::operator=(p);
231 }
232 };
233 #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
234#else
235 // Very limited implementation of unique_ptr.
236 // This is provided simply to allow the C++ code generated from the default
237 // settings to function in C++98 environments with no modifications.
238 template <class T> class unique_ptr {
239 public:
240 typedef T element_type;
241
242 unique_ptr() : ptr_(nullptr) {}
243 explicit unique_ptr(T* p) : ptr_(p) {}
244 unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); }
245 unique_ptr(const unique_ptr& u) : ptr_(nullptr) {
246 reset(const_cast<unique_ptr*>(&u)->release());
247 }
248 ~unique_ptr() { reset(); }
249
250 unique_ptr& operator=(const unique_ptr& u) {
251 reset(const_cast<unique_ptr*>(&u)->release());
252 return *this;
253 }
254
255 unique_ptr& operator=(unique_ptr&& u) {
256 reset(u.release());
257 return *this;
258 }
259
260 unique_ptr& operator=(T* p) {
261 reset(p);
262 return *this;
263 }
264
265 const T& operator*() const { return *ptr_; }
266 T* operator->() const { return ptr_; }
267 T* get() const noexcept { return ptr_; }
268 explicit operator bool() const { return ptr_ != nullptr; }
269
270 // modifiers
271 T* release() {
272 T* value = ptr_;
273 ptr_ = nullptr;
274 return value;
275 }
276
277 void reset(T* p = nullptr) {
278 T* value = ptr_;
279 ptr_ = p;
280 if (value) delete value;
281 }
282
283 void swap(unique_ptr& u) {
284 T* temp_ptr = ptr_;
285 ptr_ = u.ptr_;
286 u.ptr_ = temp_ptr;
287 }
288
289 private:
290 T* ptr_;
291 };
292
293 template <class T> bool operator==(const unique_ptr<T>& x,
294 const unique_ptr<T>& y) {
295 return x.get() == y.get();
296 }
297
298 template <class T, class D> bool operator==(const unique_ptr<T>& x,
299 const D* y) {
300 return static_cast<D*>(x.get()) == y;
301 }
302
303 template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
304 return reinterpret_cast<intptr_t>(x.get()) == y;
305 }
Austin Schuh272c6132020-11-14 16:37:52 -0800306
307 template <class T> bool operator!=(const unique_ptr<T>& x, decltype(nullptr)) {
308 return !!x;
309 }
310
311 template <class T> bool operator!=(decltype(nullptr), const unique_ptr<T>& x) {
312 return !!x;
313 }
314
315 template <class T> bool operator==(const unique_ptr<T>& x, decltype(nullptr)) {
316 return !x;
317 }
318
319 template <class T> bool operator==(decltype(nullptr), const unique_ptr<T>& x) {
320 return !x;
321 }
322
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700323#endif // !FLATBUFFERS_CPP98_STL
324
Austin Schuh272c6132020-11-14 16:37:52 -0800325#ifdef FLATBUFFERS_USE_STD_OPTIONAL
326template<class T>
327using Optional = std::optional<T>;
328using nullopt_t = std::nullopt_t;
329inline constexpr nullopt_t nullopt = std::nullopt;
330
331#else
332// Limited implementation of Optional<T> type for a scalar T.
333// This implementation limited by trivial types compatible with
334// std::is_arithmetic<T> or std::is_enum<T> type traits.
335
336// A tag to indicate an empty flatbuffers::optional<T>.
337struct nullopt_t {
338 explicit FLATBUFFERS_CONSTEXPR_CPP11 nullopt_t(int) {}
339};
340
341#if defined(FLATBUFFERS_CONSTEXPR_DEFINED)
342 namespace internal {
343 template <class> struct nullopt_holder {
344 static constexpr nullopt_t instance_ = nullopt_t(0);
345 };
346 template<class Dummy>
347 constexpr nullopt_t nullopt_holder<Dummy>::instance_;
348 }
349 static constexpr const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
350
351#else
352 namespace internal {
353 template <class> struct nullopt_holder {
354 static const nullopt_t instance_;
355 };
356 template<class Dummy>
357 const nullopt_t nullopt_holder<Dummy>::instance_ = nullopt_t(0);
358 }
359 static const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
360
361#endif
362
363template<class T>
364class Optional FLATBUFFERS_FINAL_CLASS {
365 // Non-scalar 'T' would extremely complicated Optional<T>.
366 // Use is_scalar<T> checking because flatbuffers flatbuffers::is_arithmetic<T>
367 // isn't implemented.
368 static_assert(flatbuffers::is_scalar<T>::value, "unexpected type T");
369
370 public:
371 ~Optional() {}
372
373 FLATBUFFERS_CONSTEXPR_CPP11 Optional() FLATBUFFERS_NOEXCEPT
374 : value_(), has_value_(false) {}
375
376 FLATBUFFERS_CONSTEXPR_CPP11 Optional(nullopt_t) FLATBUFFERS_NOEXCEPT
377 : value_(), has_value_(false) {}
378
379 FLATBUFFERS_CONSTEXPR_CPP11 Optional(T val) FLATBUFFERS_NOEXCEPT
380 : value_(val), has_value_(true) {}
381
382 FLATBUFFERS_CONSTEXPR_CPP11 Optional(const Optional &other) FLATBUFFERS_NOEXCEPT
383 : value_(other.value_), has_value_(other.has_value_) {}
384
385 FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(const Optional &other) FLATBUFFERS_NOEXCEPT {
386 value_ = other.value_;
387 has_value_ = other.has_value_;
388 return *this;
389 }
390
391 FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(nullopt_t) FLATBUFFERS_NOEXCEPT {
392 value_ = T();
393 has_value_ = false;
394 return *this;
395 }
396
397 FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(T val) FLATBUFFERS_NOEXCEPT {
398 value_ = val;
399 has_value_ = true;
400 return *this;
401 }
402
403 void reset() FLATBUFFERS_NOEXCEPT {
404 *this = nullopt;
405 }
406
407 void swap(Optional &other) FLATBUFFERS_NOEXCEPT {
408 std::swap(value_, other.value_);
409 std::swap(has_value_, other.has_value_);
410 }
411
412 FLATBUFFERS_CONSTEXPR_CPP11 FLATBUFFERS_EXPLICIT_CPP11 operator bool() const FLATBUFFERS_NOEXCEPT {
413 return has_value_;
414 }
415
416 FLATBUFFERS_CONSTEXPR_CPP11 bool has_value() const FLATBUFFERS_NOEXCEPT {
417 return has_value_;
418 }
419
420 FLATBUFFERS_CONSTEXPR_CPP11 const T& operator*() const FLATBUFFERS_NOEXCEPT {
421 return value_;
422 }
423
424 const T& value() const {
425 FLATBUFFERS_ASSERT(has_value());
426 return value_;
427 }
428
429 T value_or(T default_value) const FLATBUFFERS_NOEXCEPT {
430 return has_value() ? value_ : default_value;
431 }
432
433 private:
434 T value_;
435 bool has_value_;
436};
437
438template<class T>
439FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& opt, nullopt_t) FLATBUFFERS_NOEXCEPT {
440 return !opt;
441}
442template<class T>
443FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(nullopt_t, const Optional<T>& opt) FLATBUFFERS_NOEXCEPT {
444 return !opt;
445}
446
447template<class T, class U>
448FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const U& rhs) FLATBUFFERS_NOEXCEPT {
449 return static_cast<bool>(lhs) && (*lhs == rhs);
450}
451
452template<class T, class U>
453FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const T& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
454 return static_cast<bool>(rhs) && (lhs == *rhs);
455}
456
457template<class T, class U>
458FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
459 return static_cast<bool>(lhs) != static_cast<bool>(rhs)
460 ? false
461 : !static_cast<bool>(lhs) ? false : (*lhs == *rhs);
462}
463#endif // FLATBUFFERS_USE_STD_OPTIONAL
464
465
466// Very limited and naive partial implementation of C++20 std::span<T,Extent>.
467#if defined(FLATBUFFERS_USE_STD_SPAN)
468 inline constexpr std::size_t dynamic_extent = std::dynamic_extent;
469 template<class T, std::size_t Extent = std::dynamic_extent>
470 using span = std::span<T, Extent>;
471
472#else // !defined(FLATBUFFERS_USE_STD_SPAN)
473FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast<std::size_t>(-1);
474
475// Exclude this code if MSVC2010 or non-STL Android is active.
476// The non-STL Android doesn't have `std::is_convertible` required for SFINAE.
477#if !defined(FLATBUFFERS_SPAN_MINIMAL)
478namespace internal {
479 // This is SFINAE helper class for checking of a common condition:
480 // > This overload only participates in overload resolution
481 // > Check whether a pointer to an array of U can be converted
482 // > to a pointer to an array of E.
483 // This helper is used for checking of 'U -> const U'.
484 template<class E, std::size_t Extent, class U, std::size_t N>
485 struct is_span_convertable {
486 using type =
487 typename std::conditional<std::is_convertible<U (*)[], E (*)[]>::value
488 && (Extent == dynamic_extent || N == Extent),
489 int, void>::type;
490 };
491
492} // namespace internal
493#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
494
495// T - element type; must be a complete type that is not an abstract
496// class type.
497// Extent - the number of elements in the sequence, or dynamic.
498template<class T, std::size_t Extent = dynamic_extent>
499class span FLATBUFFERS_FINAL_CLASS {
500 public:
501 typedef T element_type;
502 typedef T& reference;
503 typedef const T& const_reference;
504 typedef T* pointer;
505 typedef const T* const_pointer;
506 typedef std::size_t size_type;
507
508 static FLATBUFFERS_CONSTEXPR size_type extent = Extent;
509
510 // Returns the number of elements in the span.
511 FLATBUFFERS_CONSTEXPR_CPP11 size_type size() const FLATBUFFERS_NOEXCEPT {
512 return count_;
513 }
514
515 // Returns the size of the sequence in bytes.
516 FLATBUFFERS_CONSTEXPR_CPP11
517 size_type size_bytes() const FLATBUFFERS_NOEXCEPT {
518 return size() * sizeof(element_type);
519 }
520
521 // Checks if the span is empty.
522 FLATBUFFERS_CONSTEXPR_CPP11 bool empty() const FLATBUFFERS_NOEXCEPT {
523 return size() == 0;
524 }
525
526 // Returns a pointer to the beginning of the sequence.
527 FLATBUFFERS_CONSTEXPR_CPP11 pointer data() const FLATBUFFERS_NOEXCEPT {
528 return data_;
529 }
530
531 // Returns a reference to the idx-th element of the sequence.
532 // The behavior is undefined if the idx is greater than or equal to size().
533 FLATBUFFERS_CONSTEXPR_CPP11 reference operator[](size_type idx) const {
534 return data()[idx];
535 }
536
537 FLATBUFFERS_CONSTEXPR_CPP11 span(const span &other) FLATBUFFERS_NOEXCEPT
538 : data_(other.data_), count_(other.count_) {}
539
540 FLATBUFFERS_CONSTEXPR_CPP14 span &operator=(const span &other)
541 FLATBUFFERS_NOEXCEPT {
542 data_ = other.data_;
543 count_ = other.count_;
544 }
545
546 // Limited implementation of
547 // `template <class It> constexpr std::span(It first, size_type count);`.
548 //
549 // Constructs a span that is a view over the range [first, first + count);
550 // the resulting span has: data() == first and size() == count.
551 // The behavior is undefined if [first, first + count) is not a valid range,
552 // or if (extent != flatbuffers::dynamic_extent && count != extent).
553 FLATBUFFERS_CONSTEXPR_CPP11
554 explicit span(pointer first, size_type count) FLATBUFFERS_NOEXCEPT
555 : data_ (Extent == dynamic_extent ? first : (Extent == count ? first : nullptr)),
556 count_(Extent == dynamic_extent ? count : (Extent == count ? Extent : 0)) {
557 // Make span empty if the count argument is incompatible with span<T,N>.
558 }
559
560 // Exclude this code if MSVC2010 is active. The MSVC2010 isn't C++11
561 // compliant, it doesn't support default template arguments for functions.
562 #if defined(FLATBUFFERS_SPAN_MINIMAL)
563 FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
564 count_(0) {
565 static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
566 }
567
568 #else
569 // Constructs an empty span whose data() == nullptr and size() == 0.
570 // This overload only participates in overload resolution if
571 // extent == 0 || extent == flatbuffers::dynamic_extent.
572 // A dummy template argument N is need dependency for SFINAE.
573 template<std::size_t N = 0,
574 typename internal::is_span_convertable<element_type, Extent, element_type, (N - N)>::type = 0>
575 FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
576 count_(0) {
577 static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
578 }
579
580 // Constructs a span that is a view over the array arr; the resulting span
581 // has size() == N and data() == std::data(arr). These overloads only
582 // participate in overload resolution if
583 // extent == std::dynamic_extent || N == extent is true and
584 // std::remove_pointer_t<decltype(std::data(arr))>(*)[]
585 // is convertible to element_type (*)[].
586 template<std::size_t N,
587 typename internal::is_span_convertable<element_type, Extent, element_type, N>::type = 0>
588 FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT
589 : data_(arr), count_(N) {}
590
591 template<class U, std::size_t N,
592 typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
593 FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
594 : data_(arr.data()), count_(N) {}
595
596 //template<class U, std::size_t N,
597 // int = 0>
598 //FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
599 // : data_(arr.data()), count_(N) {}
600
601 template<class U, std::size_t N,
602 typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
603 FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
604 : data_(arr.data()), count_(N) {}
605
606 // Converting constructor from another span s;
607 // the resulting span has size() == s.size() and data() == s.data().
608 // This overload only participates in overload resolution
609 // if extent == std::dynamic_extent || N == extent is true and U (*)[]
610 // is convertible to element_type (*)[].
611 template<class U, std::size_t N,
612 typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
613 FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span<U, N> &s) FLATBUFFERS_NOEXCEPT
614 : span(s.data(), s.size()) {
615 }
616
617 #endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
618
619 private:
620 // This is a naive implementation with 'count_' member even if (Extent != dynamic_extent).
621 pointer const data_;
622 const size_type count_;
623};
624
625 #if !defined(FLATBUFFERS_SPAN_MINIMAL)
626 template<class U, std::size_t N>
627 FLATBUFFERS_CONSTEXPR_CPP11
628 flatbuffers::span<U, N> make_span(U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
629 return span<U, N>(arr);
630 }
631
632 template<class U, std::size_t N>
633 FLATBUFFERS_CONSTEXPR_CPP11
634 flatbuffers::span<const U, N> make_span(const U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
635 return span<const U, N>(arr);
636 }
637
638 template<class U, std::size_t N>
639 FLATBUFFERS_CONSTEXPR_CPP11
640 flatbuffers::span<U, N> make_span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
641 return span<U, N>(arr);
642 }
643
644 template<class U, std::size_t N>
645 FLATBUFFERS_CONSTEXPR_CPP11
646 flatbuffers::span<const U, N> make_span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
647 return span<const U, N>(arr);
648 }
649
650 template<class U, std::size_t N>
651 FLATBUFFERS_CONSTEXPR_CPP11
652 flatbuffers::span<U, dynamic_extent> make_span(U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
653 return span<U, dynamic_extent>(first, count);
654 }
655
656 template<class U, std::size_t N>
657 FLATBUFFERS_CONSTEXPR_CPP11
658 flatbuffers::span<const U, dynamic_extent> make_span(const U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
659 return span<const U, dynamic_extent>(first, count);
660 }
661#endif
662
663#endif // defined(FLATBUFFERS_USE_STD_SPAN)
664
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700665} // namespace flatbuffers
666
667#endif // FLATBUFFERS_STL_EMULATION_H_