qxLib
assert_compare.h
Go to the documentation of this file.
1 /**
2 
3  @file assert_compare.h
4  @author Khrapov
5  @date 19.05.2026
6  @copyright (c) Nick Khrapov, 2026. All right reserved.
7 
8 **/
9 #pragma once
10 
11 #include <qx/algo/predicates.h>
14 
15 #include <functional>
16 #include <type_traits>
17 #include <utility>
18 
19 namespace qx
20 {
21 
22 namespace details
23 {
24 
25 /**
26 
27  @class assert_comparison
28  @brief Lightweight assertion comparison object that preserves compared operand values for diagnostics
29  @tparam left_t - left operand type
30  @tparam right_t - right operand type
31  @tparam operation_t - operation type, must be a specialization of std binary function
32  (e.g. std::equal_to<>, std::less<>, etc.)
33  @tparam bLeftIsLvalue - whether the left operand was passed as an lvalue
34  @tparam bRightIsLvalue - whether the right operand was passed as an lvalue
35  @author Khrapov
36  @date 19.05.2026
37 
38 **/
39 template<class left_t, class right_t, class operation_t, bool bLeftIsLvalue, bool bRightIsLvalue>
41 {
42 public:
43  /**
44  @brief Construct comparison object from two operands.
45  @param left - left operand
46  @param right - right operand
47  **/
48  constexpr assert_comparison(left_t&& left, right_t&& right) noexcept(
49  std::is_nothrow_constructible_v<left_t, left_t&&> && std::is_nothrow_constructible_v<right_t, right_t&&>);
50 
51  /**
52  @brief Evaluate comparison.
53  @retval - comparison result
54  **/
55  constexpr bool result() const noexcept(noexcept(operation_t {}(left(), right())));
56 
57  /**
58  @brief Convert comparison object to bool.
59  @retval - comparison result
60  **/
61  constexpr explicit operator bool() const noexcept(noexcept(result()));
62 
63  /**
64  @brief Get left operand.
65  @retval - left operand
66  **/
67  constexpr const auto& left() const noexcept;
68 
69  /**
70  @brief Get right operand.
71  @retval - right operand
72  **/
73  constexpr const auto& right() const noexcept;
74 
75 private:
76  left_t m_Left;
77  right_t m_Right;
78 };
79 
80 } // namespace details
81 
82 template<class left_t, class right_t, class operation_t, bool bLeftIsLvalue, bool bRightIsLvalue>
83 struct predicates::validator<details::assert_comparison<left_t, right_t, operation_t, bLeftIsLvalue, bRightIsLvalue>>
84 {
85  static constexpr bool is_valid(
87  value) noexcept(noexcept(value.result()));
88 };
89 
90 /**
91  @brief Compare two values for equality and preserve values for assertion diagnostics.
92  @details When used in macro assertions, this allows you to see both the names and values of variables
93  @param left - left operand
94  @param right - right operand
95  @retval - assertion comparison object
96 
97  @code
98  QX_EXPECT(qx::assert_eq(nValue, nOther)); // "nValue [41] == nOther [42]"
99  @endcode
100 **/
101 template<class left_t, class right_t>
102 constexpr auto assert_eq(left_t&& left, right_t&& right) noexcept(
104  left_t,
105  right_t,
106  std::equal_to<>,
107  std::is_lvalue_reference_v<left_t>,
108  std::is_lvalue_reference_v<right_t>>(std::forward<left_t>(left), std::forward<right_t>(right))));
109 
110 /**
111  @brief Compare two values for inequality and preserve values for assertion diagnostics.
112  @details When used in macro assertions, this allows you to see both the names and values of variables
113  @param left - left operand
114  @param right - right operand
115  @retval - assertion comparison object
116 
117  @code
118  QX_EXPECT(qx::assert_ne(nValue, nSame); // "nValue [41] != nSame [41]"
119  @endcode
120 **/
121 template<class left_t, class right_t>
122 constexpr auto assert_ne(left_t&& left, right_t&& right) noexcept(
124  left_t,
125  right_t,
126  std::not_equal_to<>,
127  std::is_lvalue_reference_v<left_t>,
128  std::is_lvalue_reference_v<right_t>>(std::forward<left_t>(left), std::forward<right_t>(right))));
129 
130 /**
131  @brief Compare whether left value is less than right value and preserve values for assertion diagnostics.
132  @details When used in macro assertions, this allows you to see both the names and values of variables
133  @param left - left operand
134  @param right - right operand
135  @retval - assertion comparison object
136 
137  @code
138  QX_EXPECT(qx::assert_lt(nOther, nValue)); // "nOther [42] < nValue [41]"
139  @endcode
140 **/
141 template<class left_t, class right_t>
142 constexpr auto assert_lt(left_t&& left, right_t&& right) noexcept(
144  left_t,
145  right_t,
146  std::less<>,
147  std::is_lvalue_reference_v<left_t>,
148  std::is_lvalue_reference_v<right_t>>(std::forward<left_t>(left), std::forward<right_t>(right))));
149 
150 /**
151  @brief Compare whether left value is less than or equal to right value and preserve values for assertion diagnostics.
152  @details When used in macro assertions, this allows you to see both the names and values of variables
153  @param left - left operand
154  @param right - right operand
155  @retval - assertion comparison object
156 
157  @code
158  QX_EXPECT(qx::assert_le(nOther, nValue)); // "nOther [42] <= nValue [41]"
159  @endcode
160 **/
161 template<class left_t, class right_t>
162 constexpr auto assert_le(left_t&& left, right_t&& right) noexcept(
164  left_t,
165  right_t,
166  std::less_equal<>,
167  std::is_lvalue_reference_v<left_t>,
168  std::is_lvalue_reference_v<right_t>>(std::forward<left_t>(left), std::forward<right_t>(right))));
169 
170 /**
171  @brief Compare whether left value is greater than right value and preserve values for assertion diagnostics.
172  @details When used in macro assertions, this allows you to see both the names and values of variables
173  @param left - left operand
174  @param right - right operand
175  @retval - assertion comparison object
176 
177  @code
178  QX_EXPECT(qx::assert_gt(nValue, nOther)); // "nValue [41] > nOther [42]"
179  @endcode
180 **/
181 template<class left_t, class right_t>
182 constexpr auto assert_gt(left_t&& left, right_t&& right) noexcept(
184  left_t,
185  right_t,
186  std::greater<>,
187  std::is_lvalue_reference_v<left_t>,
188  std::is_lvalue_reference_v<right_t>>(std::forward<left_t>(left), std::forward<right_t>(right))));
189 
190 /**
191  @brief Compare whether left value is greater than or equal to right value and preserve values for assertion diagnostics.
192  @details When used in macro assertions, this allows you to see both the names and values of variables
193  @param left - left operand
194  @param right - right operand
195  @retval - assertion comparison object
196 
197  @code
198  QX_EXPECT(qx::assert_ge(nValue, nOther)); // "nValue [41] >= nOther [42]"
199  @endcode
200 **/
201 template<class left_t, class right_t>
202 constexpr auto assert_ge(left_t&& left, right_t&& right) noexcept(
204  left_t,
205  right_t,
206  std::greater_equal<>,
207  std::is_lvalue_reference_v<left_t>,
208  std::is_lvalue_reference_v<right_t>>(std::forward<left_t>(left), std::forward<right_t>(right))));
209 
210 } // namespace qx
211 
constexpr auto assert_ge(left_t &&left, right_t &&right) noexcept(noexcept(details::assert_comparison< left_t, right_t, std::greater_equal<>, std::is_lvalue_reference_v< left_t >, std::is_lvalue_reference_v< right_t >>(std::forward< left_t >(left), std::forward< right_t >(right))))
Compare whether left value is greater than or equal to right value and preserve values for assertion ...
constexpr auto assert_le(left_t &&left, right_t &&right) noexcept(noexcept(details::assert_comparison< left_t, right_t, std::less_equal<>, std::is_lvalue_reference_v< left_t >, std::is_lvalue_reference_v< right_t >>(std::forward< left_t >(left), std::forward< right_t >(right))))
Compare whether left value is less than or equal to right value and preserve values for assertion dia...
constexpr auto assert_gt(left_t &&left, right_t &&right) noexcept(noexcept(details::assert_comparison< left_t, right_t, std::greater<>, std::is_lvalue_reference_v< left_t >, std::is_lvalue_reference_v< right_t >>(std::forward< left_t >(left), std::forward< right_t >(right))))
Compare whether left value is greater than right value and preserve values for assertion diagnostics.
constexpr auto assert_lt(left_t &&left, right_t &&right) noexcept(noexcept(details::assert_comparison< left_t, right_t, std::less<>, std::is_lvalue_reference_v< left_t >, std::is_lvalue_reference_v< right_t >>(std::forward< left_t >(left), std::forward< right_t >(right))))
Compare whether left value is less than right value and preserve values for assertion diagnostics.
constexpr auto assert_ne(left_t &&left, right_t &&right) noexcept(noexcept(details::assert_comparison< left_t, right_t, std::not_equal_to<>, std::is_lvalue_reference_v< left_t >, std::is_lvalue_reference_v< right_t >>(std::forward< left_t >(left), std::forward< right_t >(right))))
Compare two values for inequality and preserve values for assertion diagnostics.
constexpr auto assert_eq(left_t &&left, right_t &&right) noexcept(noexcept(details::assert_comparison< left_t, right_t, std::equal_to<>, std::is_lvalue_reference_v< left_t >, std::is_lvalue_reference_v< right_t >>(std::forward< left_t >(left), std::forward< right_t >(right))))
Compare two values for equality and preserve values for assertion diagnostics.
Lightweight assertion comparison object that preserves compared operand values for diagnostics.
constexpr const auto & left() const noexcept
Get left operand.
constexpr const auto & right() const noexcept
Get right operand.
constexpr bool result() const noexcept(noexcept(operation_t {}(left(), right())))
Evaluate comparison.
constexpr assert_comparison(left_t &&left, right_t &&right) noexcept(std::is_nothrow_constructible_v< left_t, left_t && > &&std::is_nothrow_constructible_v< right_t, right_t && >)
Construct comparison object from two operands.