• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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