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
87  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>>(
109  std::forward<left_t>(left),
110  std::forward<right_t>(right))));
111 
112 /**
113  @brief Compare two values for inequality and preserve values for assertion diagnostics.
114  @details When used in macro assertions, this allows you to see both the names and values of variables
115  @param left - left operand
116  @param right - right operand
117  @retval - assertion comparison object
118 
119  @code
120  QX_EXPECT(qx::assert_ne(nValue, nSame); // "nValue [41] != nSame [41]"
121  @endcode
122 **/
123 template<class left_t, class right_t>
124 constexpr auto assert_ne(left_t&& left, right_t&& right) noexcept(
126  left_t,
127  right_t,
128  std::not_equal_to<>,
129  std::is_lvalue_reference_v<left_t>,
130  std::is_lvalue_reference_v<right_t>>(
131  std::forward<left_t>(left),
132  std::forward<right_t>(right))));
133 
134 /**
135  @brief Compare whether left value is less than right value and preserve values for assertion diagnostics.
136  @details When used in macro assertions, this allows you to see both the names and values of variables
137  @param left - left operand
138  @param right - right operand
139  @retval - assertion comparison object
140 
141  @code
142  QX_EXPECT(qx::assert_lt(nOther, nValue)); // "nOther [42] < nValue [41]"
143  @endcode
144 **/
145 template<class left_t, class right_t>
146 constexpr auto assert_lt(left_t&& left, right_t&& right) noexcept(
148  left_t,
149  right_t,
150  std::less<>,
151  std::is_lvalue_reference_v<left_t>,
152  std::is_lvalue_reference_v<right_t>>(
153  std::forward<left_t>(left),
154  std::forward<right_t>(right))));
155 
156 /**
157  @brief Compare whether left value is less than or equal to right value and preserve values for assertion diagnostics.
158  @details When used in macro assertions, this allows you to see both the names and values of variables
159  @param left - left operand
160  @param right - right operand
161  @retval - assertion comparison object
162 
163  @code
164  QX_EXPECT(qx::assert_le(nOther, nValue)); // "nOther [42] <= nValue [41]"
165  @endcode
166 **/
167 template<class left_t, class right_t>
168 constexpr auto assert_le(left_t&& left, right_t&& right) noexcept(
170  left_t,
171  right_t,
172  std::less_equal<>,
173  std::is_lvalue_reference_v<left_t>,
174  std::is_lvalue_reference_v<right_t>>(
175  std::forward<left_t>(left),
176  std::forward<right_t>(right))));
177 
178 /**
179  @brief Compare whether left value is greater than right value and preserve values for assertion diagnostics.
180  @details When used in macro assertions, this allows you to see both the names and values of variables
181  @param left - left operand
182  @param right - right operand
183  @retval - assertion comparison object
184 
185  @code
186  QX_EXPECT(qx::assert_gt(nValue, nOther)); // "nValue [41] > nOther [42]"
187  @endcode
188 **/
189 template<class left_t, class right_t>
190 constexpr auto assert_gt(left_t&& left, right_t&& right) noexcept(
192  left_t,
193  right_t,
194  std::greater<>,
195  std::is_lvalue_reference_v<left_t>,
196  std::is_lvalue_reference_v<right_t>>(
197  std::forward<left_t>(left),
198  std::forward<right_t>(right))));
199 
200 /**
201  @brief Compare whether left value is greater than or equal to right value and preserve values for assertion diagnostics.
202  @details When used in macro assertions, this allows you to see both the names and values of variables
203  @param left - left operand
204  @param right - right operand
205  @retval - assertion comparison object
206 
207  @code
208  QX_EXPECT(qx::assert_ge(nValue, nOther)); // "nValue [41] >= nOther [42]"
209  @endcode
210 **/
211 template<class left_t, class right_t>
212 constexpr auto assert_ge(left_t&& left, right_t&& right) noexcept(
214  left_t,
215  right_t,
216  std::greater_equal<>,
217  std::is_lvalue_reference_v<left_t>,
218  std::is_lvalue_reference_v<right_t>>(
219  std::forward<left_t>(left),
220  std::forward<right_t>(right))));
221 
222 } // namespace qx
223 
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.