123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- // Copyright The OpenTelemetry Authors
- // SPDX-License-Identifier: Apache-2.0
- #pragma once
- // IWYU pragma: private, include "opentelemetry/nostd/variant.h"
- #include "opentelemetry/version.h"
- #include <cstddef>
- #include <memory>
- #include <utility>
- #include <variant>
- OPENTELEMETRY_BEGIN_NAMESPACE
- // Standard Type aliases in nostd namespace
- namespace nostd
- {
- using std::get_if;
- using std::monostate;
- using std::variant_alternative_t;
- // nostd::variant<...>
- template <class... _Types>
- using variant = std::variant<_Types...>;
- template <class... _Types>
- using variant_size = std::variant_size<_Types...>;
- using monostate = std::monostate;
- #if defined(__APPLE__) && defined(_LIBCPP_USE_AVAILABILITY_APPLE)
- // Apple Platforms provide std::bad_variant_access only in newer versions of OS.
- // To keep API compatible with any version of OS - we are providing our own
- // implementation of nostd::bad_variant_access exception.
- # if __EXCEPTIONS
- // nostd::bad_variant_access
- class bad_variant_access : public std::exception
- {
- public:
- virtual const char *what() const noexcept override { return "bad_variant_access"; }
- };
- [[noreturn]] inline void throw_bad_variant_access()
- {
- throw bad_variant_access{};
- }
- # endif
- # if __EXCEPTIONS
- # define THROW_BAD_VARIANT_ACCESS throw_bad_variant_access()
- # else
- # define THROW_BAD_VARIANT_ACCESS std::terminate()
- # endif
- //
- // nostd::get<...> for Apple Clang
- //
- template <typename T, class... Types>
- constexpr auto get_type = [](auto &&t) constexpr -> decltype(auto) {
- auto v = t;
- auto result = std::get_if<T>(&v); // TODO: optimize with std::forward(t) if t is not rvalue
- if (result)
- {
- return *result;
- }
- THROW_BAD_VARIANT_ACCESS;
- return *result;
- };
- template <std::size_t I, class... Types>
- constexpr auto get_index = [](auto &&t) constexpr -> decltype(auto) {
- auto v = t;
- auto result = std::get_if<I>(&v); // TODO: optimize with std::forward(t) if t is not rvalue
- if (result)
- {
- return *result;
- }
- THROW_BAD_VARIANT_ACCESS;
- return *result;
- };
- template <std::size_t I, class... Types>
- constexpr std::variant_alternative_t<I, std::variant<Types...>> &get(std::variant<Types...> &v)
- {
- return get_index<I, Types...>(v);
- };
- template <std::size_t I, class... Types>
- constexpr std::variant_alternative_t<I, std::variant<Types...>> &&get(std::variant<Types...> &&v)
- {
- return get_index<I, Types...>(std::forward<decltype(v)>(v));
- };
- template <std::size_t I, class... Types>
- constexpr const std::variant_alternative_t<I, std::variant<Types...>> &get(
- const std::variant<Types...> &v)
- {
- return get_index<I, Types...>(v);
- };
- template <std::size_t I, class... Types>
- constexpr const std::variant_alternative_t<I, std::variant<Types...>> &&get(
- const std::variant<Types...> &&v)
- {
- return get_index<I, Types...>(std::forward<decltype(v)>(v));
- };
- template <class T, class... Types>
- constexpr T &get(std::variant<Types...> &v)
- {
- return get_type<T, Types...>(v);
- };
- template <class T, class... Types>
- constexpr T /*&&*/ get(std::variant<Types...> &&v)
- {
- return get_type<T, Types...>(v);
- };
- template <class T, class... Types>
- constexpr const T &get(const std::variant<Types...> &v)
- {
- return get_type<T, Types...>(v);
- };
- template <class T, class... Types>
- constexpr const T &&get(const std::variant<Types...> &&v)
- {
- return get_type<T, Types...>(std::forward<decltype(v)>(v));
- };
- template <class _Callable, class... _Variants>
- constexpr auto visit(_Callable &&_Obj, _Variants &&..._Args)
- {
- // Ref:
- // https://stackoverflow.com/questions/52310835/xcode-10-call-to-unavailable-function-stdvisit
- return std::__variant_detail::__visitation::__variant::__visit_value(_Obj, _Args...);
- };
- #else
- using std::bad_variant_access;
- template <std::size_t I, class... Types>
- constexpr std::variant_alternative_t<I, std::variant<Types...>> &get(std::variant<Types...> &v)
- {
- return std::get<I, Types...>(v);
- }
- template <std::size_t I, class... Types>
- constexpr std::variant_alternative_t<I, std::variant<Types...>> &&get(std::variant<Types...> &&v)
- {
- return std::get<I, Types...>(std::forward<decltype(v)>(v));
- }
- template <std::size_t I, class... Types>
- constexpr const std::variant_alternative_t<I, std::variant<Types...>> &get(
- const std::variant<Types...> &v)
- {
- return std::get<I, Types...>(v);
- }
- template <std::size_t I, class... Types>
- constexpr const std::variant_alternative_t<I, std::variant<Types...>> &&get(
- const std::variant<Types...> &&v)
- {
- return std::get<I, Types...>(std::forward<decltype(v)>(v));
- }
- template <class T, class... Types>
- constexpr T &get(std::variant<Types...> &v)
- {
- return std::get<T, Types...>(v);
- }
- template <class T, class... Types>
- constexpr T &&get(std::variant<Types...> &&v)
- {
- return std::get<T, Types...>(std::forward<decltype(v)>(v));
- }
- template <class T, class... Types>
- constexpr const T &get(const std::variant<Types...> &v)
- {
- return std::get<T, Types...>(v);
- }
- template <class T, class... Types>
- constexpr const T &&get(const std::variant<Types...> &&v)
- {
- return std::get<T, Types...>(std::forward<decltype(v)>(v));
- }
- template <class _Callable, class... _Variants>
- constexpr auto visit(_Callable &&_Obj, _Variants &&..._Args)
- {
- return std::visit<_Callable, _Variants...>(static_cast<_Callable &&>(_Obj),
- static_cast<_Variants &&>(_Args)...);
- }
- #endif
- /*
- # if _HAS_CXX20
- template <class _Ret, class _Callable, class... _Variants>
- constexpr _Ret visit(_Callable &&_Obj, _Variants &&... _Args)
- {
- return std::visit<_Ret, _Callable, _Variants...>(
- static_cast<_Callable &&>(_Obj),
- static_cast<_Variants &&>(_Args)...);
- };
- # endif
- */
- // nostd::holds_alternative
- template <std::size_t I, typename... Ts>
- inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept
- {
- return v.index() == I;
- }
- template <typename T, typename... Ts>
- inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept
- {
- return std::holds_alternative<T, Ts...>(v);
- }
- } // namespace nostd
- OPENTELEMETRY_END_NAMESPACE
|