#ifndef WRAPPER_TRAITS_INL_H_ #error "Direct inclusion of this file is not allowed, include wrapper_traits.h" // For the sake of sane code completion. #include "wrapper_traits.h" #endif #include <library/cpp/yt/assert/assert.h> #include <optional> namespace NYT { //////////////////////////////////////////////////////////////////////////////// template <class T> requires std::is_object_v<T> template <class U> requires std::same_as<std::remove_cvref_t<U>, T> constexpr decltype(auto) TBasicWrapperTraits<T>::Unwrap(U&& wrapper) noexcept { return std::forward<U>(wrapper); } template <class T> requires std::is_object_v<T> constexpr bool TBasicWrapperTraits<T>::HasValue(const T&) noexcept { return true; } //////////////////////////////////////////////////////////////////////////////// template <class T> requires std::is_object_v<T> template <class U> requires std::same_as<std::remove_cvref_t<U>, T> constexpr decltype(auto) TWrapperTraits<T>::Unwrap(U&& wrapper) { YT_VERIFY(HasValue(wrapper)); return TBasicWrapperTraits<T>::Unwrap(std::forward<U>(wrapper)); } template <class T> requires std::is_object_v<T> template <class U> requires std::same_as<std::remove_cvref_t<U>, T> constexpr decltype(auto) TWrapperTraits<T>::RecursiveUnwrap(U&& wrapper) { using TDecayedU = std::remove_cvref_t<U>; using TTraits = TWrapperTraits<TDecayedU>; using TInnerTraits = TWrapperTraits<typename TTraits::TUnwrapped>; if constexpr (CNonTrivialWrapper<TDecayedU>) { return TInnerTraits::RecursiveUnwrap(TTraits::Unwrap(std::forward<U>(wrapper))); } else { return TTraits::Unwrap(std::forward<U>(wrapper)); } } template <class T> requires std::is_object_v<T> constexpr bool TWrapperTraits<T>::HasValue(const T& wrapper) noexcept { return TBasicWrapperTraits<T>::HasValue(wrapper); } template <class T> requires std::is_object_v<T> constexpr bool TWrapperTraits<T>::RecursiveHasValue(const T& wrapper) noexcept { using TTraits = TWrapperTraits<T>; using TInnerTraits = TWrapperTraits<typename TTraits::TUnwrapped>; if constexpr (CNonTrivialWrapper<T>) { return TTraits::HasValue(wrapper) && TInnerTraits::HasValue(TTraits::Unwrap(wrapper)); } else { return TTraits::HasValue(wrapper); } } template <class T> requires std::is_object_v<T> template <class U> constexpr T TWrapperTraits<T>::Wrap(U&& unwrapped) noexcept { static_assert(std::same_as<std::remove_cvref_t<U>, TUnwrapped>); return T(std::forward<U>(unwrapped)); } template <class T> requires std::is_object_v<T> template <class U> constexpr T TWrapperTraits<T>::RecursiveWrap(U&& unwrapped) noexcept { using TTraits = TWrapperTraits<T>; using TInnerTraits = TWrapperTraits<typename TTraits::TUnwrapped>; if constexpr (CNonTrivialWrapper<TUnwrapped>) { return TTraits::Wrap(TInnerTraits::RecursiveWrap(std::forward<U>(unwrapped))); } else { //! U == TUnwrapped. return TTraits::Wrap(std::forward<U>(unwrapped)); } } //////////////////////////////////////////////////////////////////////////////// //! Some standard library specializations //////////////////////////////////////////////////////////////////////////////// template <class T> struct TBasicWrapperTraits<std::optional<T>> { static constexpr bool IsTrivialWrapper = false; using TUnwrapped = T; static constexpr bool HasValue(const std::optional<T>& optional) noexcept { return optional.has_value(); } template <class U> requires std::same_as<std::remove_cvref_t<U>, std::optional<T>> static constexpr decltype(auto) Unwrap(U&& optional) { return *std::forward<U>(optional); } }; //////////////////////////////////////////////////////////////////////////////// } // namespace NYT