ops.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright (c) 2016-2025 Antony Polukhin
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_PFR_OPS_HPP
  6. #define BOOST_PFR_OPS_HPP
  7. #pragma once
  8. #include <boost/pfr/detail/config.hpp>
  9. #if !defined(BOOST_USE_MODULES) || defined(BOOST_PFR_INTERFACE_UNIT)
  10. #include <boost/pfr/detail/detectors.hpp>
  11. #include <boost/pfr/ops_fields.hpp>
  12. /// \file boost/pfr/ops.hpp
  13. /// Contains comparison and hashing functions.
  14. /// If type is comparable using its own operator or its conversion operator, then the types operator is used. Otherwise
  15. /// the operation is done via corresponding function from boost/pfr/ops.hpp header.
  16. ///
  17. /// \b Example:
  18. /// \code
  19. /// #include <boost/pfr/ops.hpp>
  20. /// struct comparable_struct { // No operators defined for that structure
  21. /// int i; short s; char data[7]; bool bl; int a,b,c,d,e,f;
  22. /// };
  23. /// // ...
  24. ///
  25. /// comparable_struct s1 {0, 1, "Hello", false, 6,7,8,9,10,11};
  26. /// comparable_struct s2 {0, 1, "Hello", false, 6,7,8,9,10,11111};
  27. /// assert(boost::pfr::lt(s1, s2));
  28. /// \endcode
  29. ///
  30. /// \podops for other ways to define operators and more details.
  31. ///
  32. /// \b Synopsis:
  33. namespace boost { namespace pfr {
  34. namespace detail {
  35. ///////////////////// Helper typedefs that are used by all the ops
  36. template <template <class, class> class Detector, class T, class U>
  37. using enable_not_comp_base_t = std::enable_if_t<
  38. not_applicable<Detector, T const&, U const&>::value,
  39. bool
  40. >;
  41. template <template <class, class> class Detector, class T, class U>
  42. using enable_comp_base_t = std::enable_if_t<
  43. !not_applicable<Detector, T const&, U const&>::value,
  44. bool
  45. >;
  46. ///////////////////// std::enable_if_t like functions that enable only if types do not support operation
  47. template <class T, class U> using enable_not_eq_comp_t = enable_not_comp_base_t<comp_eq_detector, T, U>;
  48. template <class T, class U> using enable_not_ne_comp_t = enable_not_comp_base_t<comp_ne_detector, T, U>;
  49. template <class T, class U> using enable_not_lt_comp_t = enable_not_comp_base_t<comp_lt_detector, T, U>;
  50. template <class T, class U> using enable_not_le_comp_t = enable_not_comp_base_t<comp_le_detector, T, U>;
  51. template <class T, class U> using enable_not_gt_comp_t = enable_not_comp_base_t<comp_gt_detector, T, U>;
  52. template <class T, class U> using enable_not_ge_comp_t = enable_not_comp_base_t<comp_ge_detector, T, U>;
  53. template <class T> using enable_not_hashable_t = std::enable_if_t<
  54. not_applicable<hash_detector, const T&, const T&>::value,
  55. std::size_t
  56. >;
  57. ///////////////////// std::enable_if_t like functions that enable only if types do support operation
  58. template <class T, class U> using enable_eq_comp_t = enable_comp_base_t<comp_eq_detector, T, U>;
  59. template <class T, class U> using enable_ne_comp_t = enable_comp_base_t<comp_ne_detector, T, U>;
  60. template <class T, class U> using enable_lt_comp_t = enable_comp_base_t<comp_lt_detector, T, U>;
  61. template <class T, class U> using enable_le_comp_t = enable_comp_base_t<comp_le_detector, T, U>;
  62. template <class T, class U> using enable_gt_comp_t = enable_comp_base_t<comp_gt_detector, T, U>;
  63. template <class T, class U> using enable_ge_comp_t = enable_comp_base_t<comp_ge_detector, T, U>;
  64. template <class T> using enable_hashable_t = std::enable_if_t<
  65. !not_applicable<hash_detector, const T&, const T&>::value,
  66. std::size_t
  67. >;
  68. } // namespace detail
  69. BOOST_PFR_BEGIN_MODULE_EXPORT
  70. /// \brief Compares lhs and rhs for equality using their own comparison and conversion operators; if no operators available returns \forcedlink{eq_fields}(lhs, rhs).
  71. ///
  72. /// \returns true if lhs is equal to rhs; false otherwise
  73. template <class T, class U>
  74. constexpr detail::enable_not_eq_comp_t<T, U> eq(const T& lhs, const U& rhs) noexcept {
  75. return boost::pfr::eq_fields(lhs, rhs);
  76. }
  77. /// \overload eq
  78. template <class T, class U>
  79. constexpr detail::enable_eq_comp_t<T, U> eq(const T& lhs, const U& rhs) {
  80. return lhs == rhs;
  81. }
  82. /// \brief Compares lhs and rhs for inequality using their own comparison and conversion operators; if no operators available returns \forcedlink{ne_fields}(lhs, rhs).
  83. ///
  84. /// \returns true if lhs is not equal to rhs; false otherwise
  85. template <class T, class U>
  86. constexpr detail::enable_not_ne_comp_t<T, U> ne(const T& lhs, const U& rhs) noexcept {
  87. return boost::pfr::ne_fields(lhs, rhs);
  88. }
  89. /// \overload ne
  90. template <class T, class U>
  91. constexpr detail::enable_ne_comp_t<T, U> ne(const T& lhs, const U& rhs) {
  92. return lhs != rhs;
  93. }
  94. /// \brief Compares lhs and rhs for less-than using their own comparison and conversion operators; if no operators available returns \forcedlink{lt_fields}(lhs, rhs).
  95. ///
  96. /// \returns true if lhs is less than rhs; false otherwise
  97. template <class T, class U>
  98. constexpr detail::enable_not_lt_comp_t<T, U> lt(const T& lhs, const U& rhs) noexcept {
  99. return boost::pfr::lt_fields(lhs, rhs);
  100. }
  101. /// \overload lt
  102. template <class T, class U>
  103. constexpr detail::enable_lt_comp_t<T, U> lt(const T& lhs, const U& rhs) {
  104. return lhs < rhs;
  105. }
  106. /// \brief Compares lhs and rhs for greater-than using their own comparison and conversion operators; if no operators available returns \forcedlink{lt_fields}(lhs, rhs).
  107. ///
  108. /// \returns true if lhs is greater than rhs; false otherwise
  109. template <class T, class U>
  110. constexpr detail::enable_not_gt_comp_t<T, U> gt(const T& lhs, const U& rhs) noexcept {
  111. return boost::pfr::gt_fields(lhs, rhs);
  112. }
  113. /// \overload gt
  114. template <class T, class U>
  115. constexpr detail::enable_gt_comp_t<T, U> gt(const T& lhs, const U& rhs) {
  116. return lhs > rhs;
  117. }
  118. /// \brief Compares lhs and rhs for less-equal using their own comparison and conversion operators; if no operators available returns \forcedlink{le_fields}(lhs, rhs).
  119. ///
  120. /// \returns true if lhs is less or equal to rhs; false otherwise
  121. template <class T, class U>
  122. constexpr detail::enable_not_le_comp_t<T, U> le(const T& lhs, const U& rhs) noexcept {
  123. return boost::pfr::le_fields(lhs, rhs);
  124. }
  125. /// \overload le
  126. template <class T, class U>
  127. constexpr detail::enable_le_comp_t<T, U> le(const T& lhs, const U& rhs) {
  128. return lhs <= rhs;
  129. }
  130. /// \brief Compares lhs and rhs for greater-equal using their own comparison and conversion operators; if no operators available returns \forcedlink{ge_fields}(lhs, rhs).
  131. ///
  132. /// \returns true if lhs is greater or equal to rhs; false otherwise
  133. template <class T, class U>
  134. constexpr detail::enable_not_ge_comp_t<T, U> ge(const T& lhs, const U& rhs) noexcept {
  135. return boost::pfr::ge_fields(lhs, rhs);
  136. }
  137. /// \overload ge
  138. template <class T, class U>
  139. constexpr detail::enable_ge_comp_t<T, U> ge(const T& lhs, const U& rhs) {
  140. return lhs >= rhs;
  141. }
  142. /// \brief Hashes value using its own std::hash specialization; if no std::hash specialization available returns \forcedlink{hash_fields}(value).
  143. ///
  144. /// \returns std::size_t with hash of the value
  145. template <class T>
  146. constexpr detail::enable_not_hashable_t<T> hash_value(const T& value) noexcept {
  147. return boost::pfr::hash_fields(value);
  148. }
  149. /// \overload hash_value
  150. template <class T>
  151. constexpr detail::enable_hashable_t<T> hash_value(const T& value) {
  152. return std::hash<T>{}(value);
  153. }
  154. BOOST_PFR_END_MODULE_EXPORT
  155. }} // namespace boost::pfr
  156. #endif // #if !defined(BOOST_USE_MODULES) || defined(BOOST_PFR_INTERFACE_UNIT)
  157. #endif // BOOST_PFR_OPS_HPP