wrapper_traits.h 3.2 KB

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