wrapper_traits.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #pragma once
  2. #include <concepts>
  3. #include <utility>
  4. namespace NYT {
  5. ////////////////////////////////////////////////////////////////////////////////
  6. //! Default implementation of wrapper traits you can specialize for your type
  7. template <class T>
  8. requires std::is_object_v<T>
  9. struct TBasicWrapperTraits
  10. {
  11. static constexpr bool IsTrivialWrapper = true;
  12. using TUnwrapped = T;
  13. //! Default implementations just forward the argument
  14. template <class U>
  15. requires std::same_as<std::remove_cvref_t<U>, T>
  16. static constexpr decltype(auto) Unwrap(U&& wrapper) noexcept;
  17. static constexpr bool HasValue(const T& wrapper) noexcept;
  18. };
  19. ////////////////////////////////////////////////////////////////////////////////
  20. //! Represents common denominator of every single value wrapper
  21. template <class T>
  22. requires std::is_object_v<T>
  23. struct TWrapperTraits
  24. {
  25. public:
  26. static constexpr bool IsTrivialWrapper = TBasicWrapperTraits<T>::IsTrivialWrapper;
  27. using TWrapped = T;
  28. using TUnwrapped = typename TBasicWrapperTraits<T>::TUnwrapped;
  29. static constexpr bool HasValue(const T& wrapper) noexcept;
  30. static constexpr bool RecursiveHasValue(const T& wrapper) noexcept;
  31. template <class U>
  32. requires std::same_as<std::remove_cvref_t<U>, T>
  33. static constexpr decltype(auto) Unwrap(U&& wrapper);
  34. template <class U>
  35. requires std::same_as<std::remove_cvref_t<U>, T>
  36. static constexpr decltype(auto) RecursiveUnwrap(U&& wrapper);
  37. using TRecursiveUnwrapped = std::remove_cvref_t<decltype(TWrapperTraits<T>::RecursiveUnwrap(std::declval<T>()))>;
  38. //! Unfortunatelly, clang is incapable of processing associated constraints if they depend
  39. //! on class information (e.g. aliases and static varibles) and written out-of-line.
  40. //! TODO(arkady-e1ppa): Add proper constraints when clang supports them:
  41. //! Wrap: std::same_as<std::remove_cvref_t<U>, TUnwrapped>
  42. //! RecursiveWrap: std::same_as<std::remove_cvref_t<U>, TRecursiveUnwrapped>
  43. //! Proper constructible_from checks? Easy for wrap, hard for recursive wrap.
  44. template <class U>
  45. static constexpr T Wrap(U&& unwrapped) noexcept;
  46. template <class U>
  47. static constexpr T RecursiveWrap(U&& unwrapped) noexcept;
  48. };
  49. ////////////////////////////////////////////////////////////////////////////////
  50. template <class T>
  51. concept CNonTrivialWrapper =
  52. (!TBasicWrapperTraits<T>::IsTrivialWrapper) &&
  53. requires (T& wrapper, const T& const_wrapper) {
  54. typename TBasicWrapperTraits<T>::TUnwrapped;
  55. { TBasicWrapperTraits<T>::Unwrap(wrapper) } -> std::same_as<typename TBasicWrapperTraits<T>::TUnwrapped&>;
  56. { TBasicWrapperTraits<T>::Unwrap(std::move(wrapper)) } -> std::same_as<typename TBasicWrapperTraits<T>::TUnwrapped&&>;
  57. { TBasicWrapperTraits<T>::Unwrap(const_wrapper) } -> std::same_as<const typename TBasicWrapperTraits<T>::TUnwrapped&>;
  58. { TBasicWrapperTraits<T>::HasValue(const_wrapper) } -> std::same_as<bool>;
  59. };
  60. ////////////////////////////////////////////////////////////////////////////////
  61. } // namespace NYT
  62. #define WRAPPER_TRAITS_INL_H_
  63. #include "wrapper_traits-inl.h"
  64. #undef WRAPPER_TRAITS_INL_H_