123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- // Copyright The OpenTelemetry Authors
- // SPDX-License-Identifier: Apache-2.0
- #pragma once
- // Try to use either `std::span` or `gsl::span`
- #if defined(OPENTELEMETRY_STL_VERSION)
- # if OPENTELEMETRY_STL_VERSION >= 2020
- # include <array>
- # include <cstddef>
- # include <iterator>
- # include <type_traits>
- /**
- * @brief Clang 14.0.0 with libc++ do not support implicitly construct a span
- * for a range. We just use our fallback version.
- *
- */
- # if !defined(OPENTELEMETRY_OPTION_USE_STD_SPAN) && defined(_LIBCPP_VERSION)
- # if _LIBCPP_VERSION <= 14000
- # define OPENTELEMETRY_OPTION_USE_STD_SPAN 0
- # endif
- # endif
- # ifndef OPENTELEMETRY_OPTION_USE_STD_SPAN
- # define OPENTELEMETRY_OPTION_USE_STD_SPAN 1
- # endif
- # if OPENTELEMETRY_OPTION_USE_STD_SPAN
- # include "opentelemetry/std/span.h"
- # endif
- # endif /* OPENTELEMETRY_STL_VERSION >= 2020 */
- #endif /* OPENTELEMETRY_STL_VERSION */
- // Fallback to `nostd::span` if necessary
- #if !defined(OPENTELEMETRY_HAVE_SPAN)
- # include <array>
- # include <cassert>
- # include <cstddef>
- # include <exception>
- # include <iterator>
- # include <type_traits>
- # include "opentelemetry/nostd/utility.h"
- # include "opentelemetry/version.h"
- OPENTELEMETRY_BEGIN_NAMESPACE
- namespace nostd
- {
- constexpr size_t dynamic_extent = static_cast<size_t>(-1);
- template <class T, size_t Extent = dynamic_extent>
- class span;
- namespace detail
- {
- /**
- * Helper class to resolve overloaded constructors
- */
- template <class T>
- struct is_specialized_span_convertible : std::false_type
- {};
- template <class T, size_t N>
- struct is_specialized_span_convertible<std::array<T, N>> : std::true_type
- {};
- template <class T, size_t N>
- struct is_specialized_span_convertible<T[N]> : std::true_type
- {};
- template <class T, size_t Extent>
- struct is_specialized_span_convertible<span<T, Extent>> : std::true_type
- {};
- } // namespace detail
- /**
- * Back port of std::span.
- *
- * See https://en.cppreference.com/w/cpp/container/span for interface documentation.
- *
- * Note: This provides a subset of the methods available on std::span.
- *
- * Note: The std::span API specifies error cases to have undefined behavior, so this implementation
- * chooses to terminate or assert rather than throw exceptions.
- */
- template <class T, size_t Extent>
- class span
- {
- public:
- static constexpr size_t extent = Extent;
- // This arcane code is how we make default-construction result in an SFINAE error
- // with C++11 when Extent != 0 as specified by the std::span API.
- //
- // See https://stackoverflow.com/a/10309720/4447365
- template <bool B = Extent == 0, typename std::enable_if<B>::type * = nullptr>
- span() noexcept : data_{nullptr}
- {}
- span(T *data, size_t count) noexcept : data_{data}
- {
- if (count != Extent)
- {
- std::terminate();
- }
- }
- span(T *first, T *last) noexcept : data_{first}
- {
- if (std::distance(first, last) != Extent)
- {
- std::terminate();
- }
- }
- template <size_t N, typename std::enable_if<Extent == N>::type * = nullptr>
- span(T (&array)[N]) noexcept : data_{array}
- {}
- template <size_t N, typename std::enable_if<Extent == N>::type * = nullptr>
- span(std::array<T, N> &array) noexcept : data_{array.data()}
- {}
- template <size_t N, typename std::enable_if<Extent == N>::type * = nullptr>
- span(const std::array<T, N> &array) noexcept : data_{array.data()}
- {}
- template <
- class C,
- typename std::enable_if<!detail::is_specialized_span_convertible<C>::value &&
- std::is_convertible<typename std::remove_pointer<decltype(nostd::data(
- std::declval<C &>()))>::type (*)[],
- T (*)[]>::value &&
- std::is_convertible<decltype(nostd::size(std::declval<const C &>())),
- size_t>::value>::type * = nullptr>
- span(C &c) noexcept(noexcept(nostd::data(c), nostd::size(c))) : data_{nostd::data(c)}
- {
- if (nostd::size(c) != Extent)
- {
- std::terminate();
- }
- }
- template <
- class C,
- typename std::enable_if<!detail::is_specialized_span_convertible<C>::value &&
- std::is_convertible<typename std::remove_pointer<decltype(nostd::data(
- std::declval<const C &>()))>::type (*)[],
- T (*)[]>::value &&
- std::is_convertible<decltype(nostd::size(std::declval<const C &>())),
- size_t>::value>::type * = nullptr>
- span(const C &c) noexcept(noexcept(nostd::data(c), nostd::size(c))) : data_{nostd::data(c)}
- {
- if (nostd::size(c) != Extent)
- {
- std::terminate();
- }
- }
- template <class U,
- size_t N,
- typename std::enable_if<N == Extent &&
- std::is_convertible<U (*)[], T (*)[]>::value>::type * = nullptr>
- span(const span<U, N> &other) noexcept : data_{other.data()}
- {}
- span(const span &) noexcept = default;
- span &operator=(const span &) noexcept = default;
- bool empty() const noexcept { return Extent == 0; }
- T *data() const noexcept { return data_; }
- size_t size() const noexcept { return Extent; }
- T &operator[](size_t index) const noexcept
- {
- assert(index < Extent);
- return data_[index];
- }
- T *begin() const noexcept { return data_; }
- T *end() const noexcept { return data_ + Extent; }
- private:
- T *data_;
- };
- template <class T>
- class span<T, dynamic_extent>
- {
- public:
- static constexpr size_t extent = dynamic_extent;
- span() noexcept : extent_{0}, data_{nullptr} {}
- span(T *data, size_t count) noexcept : extent_{count}, data_{data} {}
- span(T *first, T *last) noexcept
- : extent_{static_cast<size_t>(std::distance(first, last))}, data_{first}
- {
- assert(first <= last);
- }
- template <size_t N>
- span(T (&array)[N]) noexcept : extent_{N}, data_{array}
- {}
- template <size_t N>
- span(std::array<T, N> &array) noexcept : extent_{N}, data_{array.data()}
- {}
- template <size_t N>
- span(const std::array<T, N> &array) noexcept : extent_{N}, data_{array.data()}
- {}
- template <
- class C,
- typename std::enable_if<!detail::is_specialized_span_convertible<C>::value &&
- std::is_convertible<typename std::remove_pointer<decltype(nostd::data(
- std::declval<C &>()))>::type (*)[],
- T (*)[]>::value &&
- std::is_convertible<decltype(nostd::size(std::declval<const C &>())),
- size_t>::value>::type * = nullptr>
- span(C &c) noexcept(noexcept(nostd::data(c), nostd::size(c)))
- : extent_{nostd::size(c)}, data_{nostd::data(c)}
- {}
- template <
- class C,
- typename std::enable_if<!detail::is_specialized_span_convertible<C>::value &&
- std::is_convertible<typename std::remove_pointer<decltype(nostd::data(
- std::declval<const C &>()))>::type (*)[],
- T (*)[]>::value &&
- std::is_convertible<decltype(nostd::size(std::declval<const C &>())),
- size_t>::value>::type * = nullptr>
- span(const C &c) noexcept(noexcept(nostd::data(c), nostd::size(c)))
- : extent_{nostd::size(c)}, data_{nostd::data(c)}
- {}
- template <class U,
- size_t N,
- typename std::enable_if<std::is_convertible<U (*)[], T (*)[]>::value>::type * = nullptr>
- span(const span<U, N> &other) noexcept : extent_{other.size()}, data_{other.data()}
- {}
- span(const span &) noexcept = default;
- span &operator=(const span &) noexcept = default;
- bool empty() const noexcept { return extent_ == 0; }
- T *data() const noexcept { return data_; }
- size_t size() const noexcept { return extent_; }
- T &operator[](size_t index) const noexcept
- {
- assert(index < extent_);
- return data_[index];
- }
- T *begin() const noexcept { return data_; }
- T *end() const noexcept { return data_ + extent_; }
- private:
- size_t extent_;
- T *data_;
- };
- } // namespace nostd
- OPENTELEMETRY_END_NAMESPACE
- #endif
|