blob: 7ab7699641ed654362c955ab75bd7402fdc143da (
plain) (
tree)
|
|
#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
|