github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/executor/_include/flatbuffers/stl_emulation.h (about)

     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  #ifndef FLATBUFFERS_USE_STD_OPTIONAL
    30    // Detect C++17 compatible compiler.
    31    // __cplusplus >= 201703L - a compiler has support of 'static inline' variables.
    32    #if (defined(__cplusplus) && __cplusplus >= 201703L) \
    33        || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
    34      #define FLATBUFFERS_USE_STD_OPTIONAL 1
    35    #else
    36      #define FLATBUFFERS_USE_STD_OPTIONAL 0
    37    #endif // (defined(__cplusplus) && __cplusplus >= 201703L) ...
    38  #endif // FLATBUFFERS_USE_STD_OPTIONAL
    39  
    40  #if FLATBUFFERS_USE_STD_OPTIONAL
    41    #include <optional>
    42  #endif
    43  
    44  #ifndef FLATBUFFERS_USE_STD_SPAN
    45    // Testing __cpp_lib_span requires including either <version> or <span>,
    46    // both of which were added in C++20.
    47    // See: https://en.cppreference.com/w/cpp/utility/feature_test
    48    #if defined(__cplusplus) && __cplusplus >= 202002L
    49      #define FLATBUFFERS_USE_STD_SPAN 1
    50    #endif
    51  #endif // FLATBUFFERS_USE_STD_SPAN
    52  
    53  #if defined(FLATBUFFERS_USE_STD_SPAN)
    54    #include <array>
    55    #include <span>
    56  #else
    57    // Disable non-trivial ctors if FLATBUFFERS_SPAN_MINIMAL defined.
    58    #if !defined(FLATBUFFERS_TEMPLATES_ALIASES)
    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 older versions of the STL.
    67  namespace flatbuffers {
    68  
    69  #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
    70    template <typename T>
    71    using numeric_limits = std::numeric_limits<T>;
    72  #else
    73    template <typename T> class numeric_limits :
    74      public std::numeric_limits<T> {};
    75  #endif  // defined(FLATBUFFERS_TEMPLATES_ALIASES)
    76  
    77  #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
    78    template <typename T> using is_scalar = std::is_scalar<T>;
    79    template <typename T, typename U> using is_same = std::is_same<T,U>;
    80    template <typename T> using is_floating_point = std::is_floating_point<T>;
    81    template <typename T> using is_unsigned = std::is_unsigned<T>;
    82    template <typename T> using is_enum = std::is_enum<T>;
    83    template <typename T> using make_unsigned = std::make_unsigned<T>;
    84    template<bool B, class T, class F>
    85    using conditional = std::conditional<B, T, F>;
    86    template<class T, T v>
    87    using integral_constant = std::integral_constant<T, v>;
    88    template <bool B>
    89    using bool_constant = integral_constant<bool, B>;
    90    using true_type  = std::true_type;
    91    using false_type = std::false_type;
    92  #else
    93    // MSVC 2010 doesn't support C++11 aliases.
    94    template <typename T> struct is_scalar : public std::is_scalar<T> {};
    95    template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
    96    template <typename T> struct is_floating_point :
    97          public std::is_floating_point<T> {};
    98    template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
    99    template <typename T> struct is_enum : public std::is_enum<T> {};
   100    template <typename T> struct make_unsigned : public std::make_unsigned<T> {};
   101    template<bool B, class T, class F>
   102    struct conditional : public std::conditional<B, T, F> {};
   103    template<class T, T v>
   104    struct integral_constant : public std::integral_constant<T, v> {};
   105    template <bool B>
   106    struct bool_constant : public integral_constant<bool, B> {};
   107    typedef bool_constant<true>  true_type;
   108    typedef bool_constant<false> false_type;
   109  #endif  // defined(FLATBUFFERS_TEMPLATES_ALIASES)
   110  
   111  #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
   112    template <class T> using unique_ptr = std::unique_ptr<T>;
   113  #else
   114    // MSVC 2010 doesn't support C++11 aliases.
   115    // We're manually "aliasing" the class here as we want to bring unique_ptr
   116    // into the flatbuffers namespace.  We have unique_ptr in the flatbuffers
   117    // namespace we have a completely independent implementation (see below)
   118    // for C++98 STL implementations.
   119    template <class T> class unique_ptr : public std::unique_ptr<T> {
   120      public:
   121      unique_ptr() {}
   122      explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
   123      unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
   124      unique_ptr(unique_ptr&& u) { *this = std::move(u); }
   125      unique_ptr& operator=(std::unique_ptr<T>&& u) {
   126        std::unique_ptr<T>::reset(u.release());
   127        return *this;
   128      }
   129      unique_ptr& operator=(unique_ptr&& u) {
   130        std::unique_ptr<T>::reset(u.release());
   131        return *this;
   132      }
   133      unique_ptr& operator=(T* p) {
   134        return std::unique_ptr<T>::operator=(p);
   135      }
   136    };
   137  #endif  // defined(FLATBUFFERS_TEMPLATES_ALIASES)
   138  
   139  #if FLATBUFFERS_USE_STD_OPTIONAL
   140  template<class T>
   141  using Optional = std::optional<T>;
   142  using nullopt_t = std::nullopt_t;
   143  inline constexpr nullopt_t nullopt = std::nullopt;
   144  
   145  #else
   146  // Limited implementation of Optional<T> type for a scalar T.
   147  // This implementation limited by trivial types compatible with
   148  // std::is_arithmetic<T> or std::is_enum<T> type traits.
   149  
   150  // A tag to indicate an empty flatbuffers::optional<T>.
   151  struct nullopt_t {
   152    explicit FLATBUFFERS_CONSTEXPR_CPP11 nullopt_t(int) {}
   153  };
   154  
   155  #if defined(FLATBUFFERS_CONSTEXPR_DEFINED)
   156    namespace internal {
   157      template <class> struct nullopt_holder {
   158        static constexpr nullopt_t instance_ = nullopt_t(0);
   159      };
   160      template<class Dummy>
   161      constexpr nullopt_t nullopt_holder<Dummy>::instance_;
   162    }
   163    static constexpr const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
   164  
   165  #else
   166    namespace internal {
   167      template <class> struct nullopt_holder {
   168        static const nullopt_t instance_;
   169      };
   170      template<class Dummy>
   171      const nullopt_t nullopt_holder<Dummy>::instance_  = nullopt_t(0);
   172    }
   173    static const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_;
   174  
   175  #endif
   176  
   177  template<class T>
   178  class Optional FLATBUFFERS_FINAL_CLASS {
   179    // Non-scalar 'T' would extremely complicated Optional<T>.
   180    // Use is_scalar<T> checking because flatbuffers flatbuffers::is_arithmetic<T>
   181    // isn't implemented.
   182    static_assert(flatbuffers::is_scalar<T>::value, "unexpected type T");
   183  
   184   public:
   185    ~Optional() {}
   186  
   187    FLATBUFFERS_CONSTEXPR_CPP11 Optional() FLATBUFFERS_NOEXCEPT
   188      : value_(), has_value_(false) {}
   189  
   190    FLATBUFFERS_CONSTEXPR_CPP11 Optional(nullopt_t) FLATBUFFERS_NOEXCEPT
   191      : value_(), has_value_(false) {}
   192  
   193    FLATBUFFERS_CONSTEXPR_CPP11 Optional(T val) FLATBUFFERS_NOEXCEPT
   194      : value_(val), has_value_(true) {}
   195  
   196    FLATBUFFERS_CONSTEXPR_CPP11 Optional(const Optional &other) FLATBUFFERS_NOEXCEPT
   197      : value_(other.value_), has_value_(other.has_value_) {}
   198  
   199    FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(const Optional &other) FLATBUFFERS_NOEXCEPT {
   200      value_ = other.value_;
   201      has_value_ = other.has_value_;
   202      return *this;
   203    }
   204  
   205    FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(nullopt_t) FLATBUFFERS_NOEXCEPT {
   206      value_ = T();
   207      has_value_ = false;
   208      return *this;
   209    }
   210  
   211    FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(T val) FLATBUFFERS_NOEXCEPT {
   212      value_ = val;
   213      has_value_ = true;
   214      return *this;
   215    }
   216  
   217    void reset() FLATBUFFERS_NOEXCEPT {
   218      *this = nullopt;
   219    }
   220  
   221    void swap(Optional &other) FLATBUFFERS_NOEXCEPT {
   222      std::swap(value_, other.value_);
   223      std::swap(has_value_, other.has_value_);
   224    }
   225  
   226    FLATBUFFERS_CONSTEXPR_CPP11 FLATBUFFERS_EXPLICIT_CPP11 operator bool() const FLATBUFFERS_NOEXCEPT {
   227      return has_value_;
   228    }
   229  
   230    FLATBUFFERS_CONSTEXPR_CPP11 bool has_value() const FLATBUFFERS_NOEXCEPT {
   231      return has_value_;
   232    }
   233  
   234    FLATBUFFERS_CONSTEXPR_CPP11 const T& operator*() const FLATBUFFERS_NOEXCEPT {
   235      return value_;
   236    }
   237  
   238    const T& value() const {
   239      FLATBUFFERS_ASSERT(has_value());
   240      return value_;
   241    }
   242  
   243    T value_or(T default_value) const FLATBUFFERS_NOEXCEPT {
   244      return has_value() ? value_ : default_value;
   245    }
   246  
   247   private:
   248    T value_;
   249    bool has_value_;
   250  };
   251  
   252  template<class T>
   253  FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& opt, nullopt_t) FLATBUFFERS_NOEXCEPT {
   254    return !opt;
   255  }
   256  template<class T>
   257  FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(nullopt_t, const Optional<T>& opt) FLATBUFFERS_NOEXCEPT {
   258    return !opt;
   259  }
   260  
   261  template<class T, class U>
   262  FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const U& rhs) FLATBUFFERS_NOEXCEPT {
   263    return static_cast<bool>(lhs) && (*lhs == rhs);
   264  }
   265  
   266  template<class T, class U>
   267  FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const T& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
   268    return static_cast<bool>(rhs) && (lhs == *rhs);
   269  }
   270  
   271  template<class T, class U>
   272  FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT {
   273    return static_cast<bool>(lhs) != static_cast<bool>(rhs)
   274                ? false
   275                : !static_cast<bool>(lhs) ? false : (*lhs == *rhs);
   276  }
   277  #endif // FLATBUFFERS_USE_STD_OPTIONAL
   278  
   279  
   280  // Very limited and naive partial implementation of C++20 std::span<T,Extent>.
   281  #if defined(FLATBUFFERS_USE_STD_SPAN)
   282    inline constexpr std::size_t dynamic_extent = std::dynamic_extent;
   283    template<class T, std::size_t Extent = std::dynamic_extent>
   284    using span = std::span<T, Extent>;
   285  
   286  #else // !defined(FLATBUFFERS_USE_STD_SPAN)
   287  FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast<std::size_t>(-1);
   288  
   289  // Exclude this code if MSVC2010 or non-STL Android is active.
   290  // The non-STL Android doesn't have `std::is_convertible` required for SFINAE.
   291  #if !defined(FLATBUFFERS_SPAN_MINIMAL)
   292  namespace internal {
   293    // This is SFINAE helper class for checking of a common condition:
   294    // > This overload only participates in overload resolution
   295    // > Check whether a pointer to an array of From can be converted
   296    // > to a pointer to an array of To.
   297    // This helper is used for checking of 'From -> const From'.
   298    template<class To, std::size_t Extent, class From, std::size_t N>
   299    struct is_span_convertible {
   300      using type =
   301        typename std::conditional<std::is_convertible<From (*)[], To (*)[]>::value
   302                                  && (Extent == dynamic_extent || N == Extent),
   303                                  int, void>::type;
   304    };
   305  
   306    template<typename T>
   307    struct SpanIterator {
   308      // TODO: upgrade to std::random_access_iterator_tag.
   309      using iterator_category = std::forward_iterator_tag;
   310      using difference_type  = std::ptrdiff_t;
   311      using value_type = typename std::remove_cv<T>::type;
   312      using reference = T&;
   313      using pointer   = T*;
   314  
   315      // Convince MSVC compiler that this iterator is trusted (it is verified).
   316      #ifdef _MSC_VER
   317        using _Unchecked_type = pointer;
   318      #endif // _MSC_VER
   319  
   320      SpanIterator(pointer ptr) : ptr_(ptr) {}
   321      reference operator*() const { return *ptr_; }
   322      pointer operator->() { return ptr_; }
   323      SpanIterator& operator++() { ptr_++; return *this; }  
   324      SpanIterator  operator++(int) { auto tmp = *this; ++(*this); return tmp; }
   325  
   326      friend bool operator== (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ == rhs.ptr_; }
   327      friend bool operator!= (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ != rhs.ptr_; }
   328  
   329     private:
   330      pointer ptr_;
   331    };
   332  }  // namespace internal
   333  #endif  // !defined(FLATBUFFERS_SPAN_MINIMAL)
   334  
   335  // T - element type; must be a complete type that is not an abstract
   336  // class type.
   337  // Extent - the number of elements in the sequence, or dynamic.
   338  template<class T, std::size_t Extent = dynamic_extent>
   339  class span FLATBUFFERS_FINAL_CLASS {
   340   public:
   341    typedef T element_type;
   342    typedef T& reference;
   343    typedef const T& const_reference;
   344    typedef T* pointer;
   345    typedef const T* const_pointer;
   346    typedef std::size_t size_type;
   347  
   348    static FLATBUFFERS_CONSTEXPR size_type extent = Extent;
   349  
   350    // Returns the number of elements in the span.
   351    FLATBUFFERS_CONSTEXPR_CPP11 size_type size() const FLATBUFFERS_NOEXCEPT {
   352      return count_;
   353    }
   354  
   355    // Returns the size of the sequence in bytes.
   356    FLATBUFFERS_CONSTEXPR_CPP11
   357    size_type size_bytes() const FLATBUFFERS_NOEXCEPT {
   358      return size() * sizeof(element_type);
   359    }
   360  
   361    // Checks if the span is empty.
   362    FLATBUFFERS_CONSTEXPR_CPP11 bool empty() const FLATBUFFERS_NOEXCEPT {
   363      return size() == 0;
   364    }
   365  
   366    // Returns a pointer to the beginning of the sequence.
   367    FLATBUFFERS_CONSTEXPR_CPP11 pointer data() const FLATBUFFERS_NOEXCEPT {
   368      return data_;
   369    }
   370  
   371    #if !defined(FLATBUFFERS_SPAN_MINIMAL)
   372      using Iterator = internal::SpanIterator<T>;
   373  
   374      Iterator begin() const { return Iterator(data()); }
   375      Iterator end() const   { return Iterator(data() + size()); }
   376    #endif
   377  
   378    // Returns a reference to the idx-th element of the sequence.
   379    // The behavior is undefined if the idx is greater than or equal to size().
   380    FLATBUFFERS_CONSTEXPR_CPP11 reference operator[](size_type idx) const {
   381      return data()[idx];
   382    }
   383  
   384    FLATBUFFERS_CONSTEXPR_CPP11 span(const span &other) FLATBUFFERS_NOEXCEPT
   385        : data_(other.data_), count_(other.count_) {}
   386  
   387    FLATBUFFERS_CONSTEXPR_CPP14 span &operator=(const span &other)
   388        FLATBUFFERS_NOEXCEPT {
   389      data_ = other.data_;
   390      count_ = other.count_;
   391    }
   392  
   393    // Limited implementation of
   394    // `template <class It> constexpr std::span(It first, size_type count);`.
   395    //
   396    // Constructs a span that is a view over the range [first, first + count);
   397    // the resulting span has: data() == first and size() == count.
   398    // The behavior is undefined if [first, first + count) is not a valid range,
   399    // or if (extent != flatbuffers::dynamic_extent && count != extent).
   400    FLATBUFFERS_CONSTEXPR_CPP11
   401    explicit span(pointer first, size_type count) FLATBUFFERS_NOEXCEPT
   402      : data_ (Extent == dynamic_extent ? first : (Extent == count ? first : nullptr)),
   403        count_(Extent == dynamic_extent ? count : (Extent == count ? Extent : 0)) {
   404        // Make span empty if the count argument is incompatible with span<T,N>.
   405    }
   406  
   407    // Exclude this code if MSVC2010 is active. The MSVC2010 isn't C++11
   408    // compliant, it doesn't support default template arguments for functions.
   409    #if defined(FLATBUFFERS_SPAN_MINIMAL)
   410    FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
   411                                                              count_(0) {
   412      static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
   413    }
   414  
   415    #else
   416    // Constructs an empty span whose data() == nullptr and size() == 0.
   417    // This overload only participates in overload resolution if
   418    // extent == 0 || extent == flatbuffers::dynamic_extent.
   419    // A dummy template argument N is need dependency for SFINAE.
   420    template<std::size_t N = 0,
   421      typename internal::is_span_convertible<element_type, Extent, element_type, (N - N)>::type = 0>
   422    FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
   423                                                              count_(0) {
   424      static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
   425    }
   426  
   427    // Constructs a span that is a view over the array arr; the resulting span
   428    // has size() == N and data() == std::data(arr). These overloads only
   429    // participate in overload resolution if
   430    // extent == std::dynamic_extent || N == extent is true and
   431    // std::remove_pointer_t<decltype(std::data(arr))>(*)[]
   432    // is convertible to element_type (*)[].
   433    template<std::size_t N,
   434      typename internal::is_span_convertible<element_type, Extent, element_type, N>::type = 0>
   435    FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT
   436        : data_(arr), count_(N) {}
   437  
   438    template<class U, std::size_t N,
   439      typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
   440    FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
   441       : data_(arr.data()), count_(N) {}
   442  
   443    //template<class U, std::size_t N,
   444    //  int = 0>
   445    //FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
   446    //   : data_(arr.data()), count_(N) {}
   447  
   448    template<class U, std::size_t N,
   449      typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
   450    FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
   451      : data_(arr.data()), count_(N) {}
   452  
   453    // Converting constructor from another span s;
   454    // the resulting span has size() == s.size() and data() == s.data().
   455    // This overload only participates in overload resolution
   456    // if extent == std::dynamic_extent || N == extent is true and U (*)[]
   457    // is convertible to element_type (*)[].
   458    template<class U, std::size_t N,
   459      typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
   460    FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span<U, N> &s) FLATBUFFERS_NOEXCEPT
   461        : span(s.data(), s.size()) {
   462    }
   463  
   464    #endif  // !defined(FLATBUFFERS_SPAN_MINIMAL)
   465  
   466   private:
   467    // This is a naive implementation with 'count_' member even if (Extent != dynamic_extent).
   468    pointer const data_;
   469    size_type count_;
   470  };
   471  #endif  // defined(FLATBUFFERS_USE_STD_SPAN)
   472  
   473  #if !defined(FLATBUFFERS_SPAN_MINIMAL)
   474  template<class ElementType, std::size_t Extent>
   475  FLATBUFFERS_CONSTEXPR_CPP11
   476  flatbuffers::span<ElementType, Extent> make_span(ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT {
   477    return span<ElementType, Extent>(arr);
   478  }
   479  
   480  template<class ElementType, std::size_t Extent>
   481  FLATBUFFERS_CONSTEXPR_CPP11
   482  flatbuffers::span<const ElementType, Extent> make_span(const ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT {
   483    return span<const ElementType, Extent>(arr);
   484  }
   485  
   486  template<class ElementType, std::size_t Extent>
   487  FLATBUFFERS_CONSTEXPR_CPP11
   488  flatbuffers::span<ElementType, Extent> make_span(std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT {
   489    return span<ElementType, Extent>(arr);
   490  }
   491  
   492  template<class ElementType, std::size_t Extent>
   493  FLATBUFFERS_CONSTEXPR_CPP11
   494  flatbuffers::span<const ElementType, Extent> make_span(const std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT {
   495    return span<const ElementType, Extent>(arr);
   496  }
   497  
   498  template<class ElementType, std::size_t Extent>
   499  FLATBUFFERS_CONSTEXPR_CPP11
   500  flatbuffers::span<ElementType, dynamic_extent> make_span(ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
   501    return span<ElementType, dynamic_extent>(first, count);
   502  }
   503  
   504  template<class ElementType, std::size_t Extent>
   505  FLATBUFFERS_CONSTEXPR_CPP11
   506  flatbuffers::span<const ElementType, dynamic_extent> make_span(const ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
   507    return span<const ElementType, dynamic_extent>(first, count);
   508  }
   509  #endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
   510  
   511  }  // namespace flatbuffers
   512  
   513  #endif  // FLATBUFFERS_STL_EMULATION_H_