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