@micro-os-plus/micro-test-plus 3.3.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +330 -2
  2. package/CMakeLists.txt +79 -23
  3. package/README.md +1 -1
  4. package/config/xcdl-build.json +11 -4
  5. package/include/micro-os-plus/micro-test-plus/deferred-reporter.h +292 -0
  6. package/include/micro-os-plus/micro-test-plus/detail.h +462 -1076
  7. package/include/micro-os-plus/micro-test-plus/exceptions.h +126 -0
  8. package/include/micro-os-plus/micro-test-plus/function-comparators.h +10 -7
  9. package/include/micro-os-plus/micro-test-plus/inlines/{details-inlines.h → deferred-reporter-inlines.h} +49 -22
  10. package/include/micro-os-plus/micro-test-plus/inlines/function-comparators-inlines.h +67 -4
  11. package/include/micro-os-plus/micro-test-plus/inlines/literals-inlines.h +3 -6
  12. package/include/micro-os-plus/micro-test-plus/inlines/math-inlines.h +21 -15
  13. package/include/micro-os-plus/micro-test-plus/inlines/reflection-inlines.h +35 -17
  14. package/include/micro-os-plus/micro-test-plus/inlines/{test-reporter-inlines.h → reporter-inlines.h} +176 -106
  15. package/include/micro-os-plus/micro-test-plus/inlines/{test-suite-inlines.h → runner-inlines.h} +41 -43
  16. package/include/micro-os-plus/micro-test-plus/inlines/test-inlines.h +369 -0
  17. package/include/micro-os-plus/micro-test-plus/inlines/utility-inlines.h +126 -0
  18. package/include/micro-os-plus/micro-test-plus/literals.h +4 -3
  19. package/include/micro-os-plus/micro-test-plus/math.h +9 -6
  20. package/include/micro-os-plus/micro-test-plus/operators.h +38 -44
  21. package/include/micro-os-plus/micro-test-plus/reflection.h +15 -4
  22. package/include/micro-os-plus/micro-test-plus/{test-reporter-basic.h → reporter-human.h} +72 -72
  23. package/include/micro-os-plus/micro-test-plus/{test-reporter-tap.h → reporter-tap.h} +69 -69
  24. package/include/micro-os-plus/micro-test-plus/{test-reporter.h → reporter.h} +296 -200
  25. package/include/micro-os-plus/micro-test-plus/runner-totals.h +264 -0
  26. package/include/micro-os-plus/micro-test-plus/runner.h +453 -0
  27. package/include/micro-os-plus/micro-test-plus/test.h +1069 -0
  28. package/include/micro-os-plus/micro-test-plus/timings.h +366 -0
  29. package/include/micro-os-plus/micro-test-plus/type-traits.h +239 -545
  30. package/include/micro-os-plus/micro-test-plus/utility.h +135 -0
  31. package/include/micro-os-plus/micro-test-plus.h +25 -228
  32. package/meson.build +10 -6
  33. package/package.json +1 -1
  34. package/src/deferred-reporter.cpp +118 -0
  35. package/src/reflection.cpp +95 -0
  36. package/src/reporter-human.cpp +822 -0
  37. package/src/reporter-tap.cpp +782 -0
  38. package/src/reporter.cpp +676 -0
  39. package/src/runner-totals.cpp +95 -0
  40. package/src/runner.cpp +563 -0
  41. package/src/test.cpp +496 -0
  42. package/src/timings.cpp +209 -0
  43. package/src/utility.cpp +163 -0
  44. package/.cmake-format.yaml +0 -11
  45. package/include/micro-os-plus/micro-test-plus/inlines/micro-test-plus-inlines.h +0 -313
  46. package/include/micro-os-plus/micro-test-plus/test-runner.h +0 -281
  47. package/include/micro-os-plus/micro-test-plus/test-suite.h +0 -492
  48. package/src/micro-test-plus.cpp +0 -316
  49. package/src/test-reporter-basic.cpp +0 -466
  50. package/src/test-reporter-tap.cpp +0 -530
  51. package/src/test-reporter.cpp +0 -399
  52. package/src/test-runner.cpp +0 -311
  53. package/src/test-suite.cpp +0 -304
@@ -48,7 +48,7 @@
48
48
 
49
49
  // ----------------------------------------------------------------------------
50
50
 
51
- #include <stdio.h>
51
+ #include <cstdio>
52
52
  #include <string>
53
53
 
54
54
  // ----------------------------------------------------------------------------
@@ -62,8 +62,12 @@
62
62
  #endif
63
63
  #endif
64
64
 
65
+ // ============================================================================
66
+
65
67
  namespace micro_os_plus::micro_test_plus
66
68
  {
69
+ class test_node;
70
+
67
71
  // --------------------------------------------------------------------------
68
72
 
69
73
  /**
@@ -137,48 +141,13 @@ namespace micro_os_plus::micro_test_plus
137
141
  * @return The value obtained via the relevant getter implementation.
138
142
  *
139
143
  * @details
140
- * The `get` function template invokes the appropriate getter
141
- * implementation to retrieve the value from the provided object or type.
142
- * This function ensures consistent access to values for both custom and
143
- * standard types within the framework.
144
- *
145
- * The primary implementation attempts to invoke a `get()` method if it
146
- * exists, which is recommended for user-defined types to ensure consistent
147
- * value access. If the type does not provide a `get()` method, the
148
- * fallback variadic implementation simply returns the original argument.
149
- *
150
- * The `get` function template delegates to these implementations, enabling
151
- * seamless support for a wide range of types in test expressions and
152
- * comparators.
153
- *
154
- * All definitions are intended for internal use within the framework and
155
- * are implemented in the `include/micro-os-plus/micro-test-plus` folder to
156
- * maintain a structured and modular codebase.
157
- */
158
- template <class T>
159
- [[nodiscard]] constexpr auto
160
- get_impl (const T& t, int) -> decltype (t.get ())
161
- {
162
- return t.get ();
163
- }
164
-
165
- /**
166
- * @brief Fallback variadic getter function template.
167
- *
168
- * @tparam T The type from which the value is to be retrieved.
169
- *
170
- * @param t The object or value to be accessed.
171
- * @return The original argument `t`.
172
- *
173
- * @details
174
- * The `get_impl` function template serves as a fallback mechanism for
175
- * value retrieval when the provided type does not implement a `get()`
176
- * member function. It simply returns the first argument, discarding any
177
- * additional parameters.
144
+ * The `get` function template retrieves the value from the provided
145
+ * object or type. If the type provides a `get()` member function, it
146
+ * is invoked; otherwise the argument itself is returned unchanged.
178
147
  *
179
- * This approach ensures that both custom types (with a `get()` method) and
180
- * standard types (without a `get()` method) are supported seamlessly
181
- * within the framework's generic getter utilities.
148
+ * The selection is performed at compile time using `if constexpr` and
149
+ * an inline `requires` expression, superseding the classic two-overload
150
+ * SFINAE technique used prior to C++20.
182
151
  *
183
152
  * All definitions are intended for internal use within the framework and
184
153
  * are implemented in the `include/micro-os-plus/micro-test-plus` folder to
@@ -186,148 +155,139 @@ namespace micro_os_plus::micro_test_plus
186
155
  */
187
156
  template <class T>
188
157
  [[nodiscard]] constexpr auto
189
- get_impl (const T& t, ...) -> decltype (auto)
158
+ get (const T& t)
190
159
  {
191
- return t;
160
+ if constexpr (requires { t.get (); })
161
+ return t.get ();
162
+ else
163
+ return t;
192
164
  }
193
165
 
166
+ // ------------------------------------------------------------------------
167
+
194
168
  /**
195
- * @brief Generic getter function template for value retrieval.
169
+ * @brief Common base struct template for unary comparators.
196
170
  *
197
- * @tparam T The type from which the value is to be retrieved.
198
- *
199
- * @param t The object or value to be accessed.
200
- * @return The value obtained via the relevant getter implementation.
171
+ * @tparam T The type of the operand.
201
172
  *
202
173
  * @details
203
- * The `get` function template invokes the appropriate getter
204
- * implementation to retrieve the value from the provided object or type.
205
- * This function ensures consistent access to values for both custom and
206
- * standard types within the framework.
207
- *
208
- * The primary implementation attempts to invoke a `get()` method if it
209
- * exists, which is recommended for user-defined types to ensure consistent
210
- * value access. If the type does not provide a `get()` method, the
211
- * fallback variadic implementation simply returns the original argument.
212
- *
213
- * The `get` function template delegates to these implementations, enabling
214
- * seamless support for a wide range of types in test expressions and
215
- * comparators.
174
+ * The `unary_op_` struct template provides the shared state and
175
+ * interface for unary comparator types within the framework. It stores
176
+ * the single operand and the boolean result of the operation, and
177
+ * exposes a conversion operator and an operand accessor common to all
178
+ * unary comparators.
179
+ *
180
+ * Derived comparator structs (e.g. `not_`) inherit from this base and
181
+ * supply the operation-specific logic via their constructors.
182
+ *
183
+ * All definitions are intended for internal use within the framework
184
+ * and are implemented in the
185
+ * `include/micro-os-plus/micro-test-plus` folder to maintain a
186
+ * structured and modular codebase.
216
187
  *
217
- * All definitions are intended for internal use within the framework and
218
- * are implemented in the `include/micro-os-plus/micro-test-plus` folder to
219
- * maintain a structured and modular codebase.
188
+ * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
220
189
  */
221
190
  template <class T>
222
- [[nodiscard]] constexpr auto
223
- get (const T& t)
191
+ struct unary_op_ : type_traits::op
224
192
  {
225
- // Call the variadic function, basically to force it return `t`.
226
- return get_impl<T> (t, 0);
227
- }
193
+ /**
194
+ * @brief Constructs a unary comparator with the given operand and
195
+ * pre-computed result.
196
+ *
197
+ * @param t The operand.
198
+ * @param value The pre-computed boolean result of the operation.
199
+ */
200
+ constexpr unary_op_ (const T& t, bool value) : t_{ t }, value_{ value }
201
+ {
202
+ }
203
+
204
+ /**
205
+ * @brief Conversion operator to boolean.
206
+ *
207
+ * @par Parameters
208
+ * None.
209
+ * @return The result of the operation.
210
+ *
211
+ * @details
212
+ * Returns the pre-computed boolean result stored by the derived
213
+ * comparator's constructor.
214
+ */
215
+ [[nodiscard]] constexpr
216
+ operator bool () const
217
+ {
218
+ return value_;
219
+ }
220
+
221
+ /**
222
+ * @brief Retrieves the wrapped operand expression.
223
+ *
224
+ * @par Parameters
225
+ * None.
226
+ * @return The extracted operand value.
227
+ *
228
+ * @details
229
+ * Returns the wrapped operand, applying the generic getter to
230
+ * ensure correct extraction for both custom and standard types.
231
+ * Named `operand()` to distinguish it from the boolean result
232
+ * stored in `value_`.
233
+ */
234
+ [[nodiscard]] constexpr auto
235
+ operand () const
236
+ {
237
+ return get (t_);
238
+ }
239
+
240
+ private:
241
+ /**
242
+ * @brief Stores the operand.
243
+ */
244
+ const T t_{};
245
+
246
+ /**
247
+ * @brief Stores the result of the operation.
248
+ */
249
+ const bool value_{};
250
+ };
228
251
 
229
252
  // ------------------------------------------------------------------------
230
253
 
231
254
  /**
232
- * @brief Equality comparator struct template.
255
+ * @brief Common base struct template for binary comparators.
233
256
  *
234
257
  * @tparam Lhs_T The type of the left-hand operand.
235
258
  * @tparam Rhs_T The type of the right-hand operand.
236
259
  *
237
260
  * @details
238
- * The `eq_` struct template provides a type-safe mechanism for evaluating
239
- * equality between two operands within the framework.
240
- *
241
- * This comparator supports a variety of operand types, including those
242
- * with static values, types with precision (epsilon), and generic types.
243
- * For types with static values, the comparison is performed directly. For
244
- * types supporting precision, the comparison accounts for the smallest
245
- * epsilon to ensure accuracy, particularly for floating-point types. For
246
- * all other types, the generic getter is used to retrieve and compare the
247
- * values.
261
+ * The `binary_op_` struct template provides the shared state and interface
262
+ * for all binary comparator types within the framework. It stores the
263
+ * two operands and the boolean result of the comparison, and exposes
264
+ * a conversion operator and value accessors common to all binary
265
+ * comparators.
248
266
  *
249
- * The implementation is optimised for use in embedded environments and
250
- * supports both compile-time and run-time evaluation.
267
+ * Derived comparator structs (`eq_`, `ne_`, `gt_`, `ge_`, `lt_`, `le_`,
268
+ * `and_`, `or_`) inherit from this base and supply the
269
+ * operation-specific logic via their constructors.
251
270
  *
252
- * All definitions are intended for internal use within the framework and
253
- * are implemented in the `include/micro-os-plus/micro-test-plus` folder to
254
- * maintain a structured and modular codebase.
271
+ * All definitions are intended for internal use within the framework
272
+ * and are implemented in the
273
+ * `include/micro-os-plus/micro-test-plus` folder to maintain a
274
+ * structured and modular codebase.
255
275
  *
256
276
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
257
277
  */
258
278
  template <class Lhs_T, class Rhs_T>
259
- struct eq_ : type_traits::op
279
+ struct binary_op_ : type_traits::op
260
280
  {
261
281
  /**
262
- * @brief Constructs an equality comparator for the given operands.
282
+ * @brief Constructs a binary comparator with the given operands and
283
+ * pre-computed result.
263
284
  *
264
285
  * @param lhs The left-hand operand.
265
286
  * @param rhs The right-hand operand.
266
- *
267
- * @details
268
- * Evaluates the equality of the provided operands at construction,
269
- * supporting static values, types with precision, and generic types. The
270
- * result is stored in the `value_` member for efficient access.
287
+ * @param value The pre-computed boolean result of the comparison.
271
288
  */
272
- constexpr eq_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
273
- : lhs_{ lhs }, rhs_{ rhs }, value_{
274
- [&]
275
- {
276
- // This lambda is called in the constructor to
277
- // evaluate the comparison.
278
- using std::operator==;
279
- using std::operator<;
280
-
281
- #if defined(__GNUC__)
282
- #pragma GCC diagnostic push
283
- #pragma GCC diagnostic ignored "-Wfloat-equal"
284
- #pragma GCC diagnostic ignored "-Wconversion"
285
- #pragma GCC diagnostic ignored "-Wdouble-promotion"
286
- #pragma GCC diagnostic ignored "-Wsign-compare"
287
- #if defined(__clang__)
288
- #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
289
- #pragma clang diagnostic ignored "-Wpedantic"
290
- #endif
291
- #endif
292
- if constexpr (type_traits::has_value_v<Lhs_T>
293
- and type_traits::has_value_v<Rhs_T>)
294
- {
295
- // If both types have values (like numeric constants),
296
- // compare them directly.
297
- return Lhs_T::value == Rhs_T::value;
298
- }
299
- else if constexpr (type_traits::has_epsilon_v<Lhs_T>
300
- and type_traits::has_epsilon_v<Rhs_T>)
301
- {
302
- // If both values have precision, compare them using
303
- // the smalles precision.
304
- return math::abs (get (lhs) - get (rhs))
305
- < math::min_value (Lhs_T::epsilon,
306
- Rhs_T::epsilon);
307
- }
308
- else if constexpr (type_traits::has_epsilon_v<Lhs_T>)
309
- {
310
- // If only the left operand has precision, use it.
311
- return math::abs (get (lhs) - get (rhs))
312
- < Lhs_T::epsilon;
313
- }
314
- else if constexpr (type_traits::has_epsilon_v<Rhs_T>)
315
- {
316
- // If only the right operand has precision, use it.
317
- return math::abs (get (lhs) - get (rhs))
318
- < Rhs_T::epsilon;
319
- }
320
- else
321
- {
322
- // Call the generic getters, which might
323
- // either call the type get() or return the value.
324
- return get (lhs) == get (rhs);
325
- }
326
- #if defined(__GNUC__)
327
- #pragma GCC diagnostic pop
328
- #endif
329
- }()
330
- }
289
+ constexpr binary_op_ (const Lhs_T& lhs, const Rhs_T& rhs, bool value)
290
+ : lhs_{ lhs }, rhs_{ rhs }, value_{ value }
331
291
  {
332
292
  }
333
293
 
@@ -336,11 +296,11 @@ namespace micro_os_plus::micro_test_plus
336
296
  *
337
297
  * @par Parameters
338
298
  * None.
339
- * @retval true The operands are considered equal.
340
- * @retval false The operands are not equal.
299
+ * @return The result of the comparison.
341
300
  *
342
301
  * @details
343
- * Returns the result of the equality comparison.
302
+ * Returns the pre-computed boolean result stored by the derived
303
+ * comparator's constructor.
344
304
  */
345
305
  [[nodiscard]] constexpr
346
306
  operator bool () const
@@ -384,37 +344,40 @@ namespace micro_os_plus::micro_test_plus
384
344
  return get (rhs_);
385
345
  }
386
346
 
347
+ private:
387
348
  /**
388
349
  * @brief Stores the left-hand operand.
350
+ *
351
+ * @note Operands are stored by value; passing a large container
352
+ * will copy it into this member.
389
353
  */
390
354
  const Lhs_T lhs_{};
391
355
 
392
356
  /**
393
357
  * @brief Stores the right-hand operand.
358
+ *
359
+ * @note Operands are stored by value; passing a large container
360
+ * will copy it into this member.
394
361
  */
395
362
  const Rhs_T rhs_{};
396
363
 
397
364
  /**
398
- * @brief Stores the result of the equality comparison.
365
+ * @brief Stores the result of the comparison.
399
366
  */
400
367
  const bool value_{};
401
368
  };
402
369
 
403
- // Deduction guide.
404
- template <typename Lhs_T, typename Rhs_T>
405
- eq_ (const Lhs_T&, const Rhs_T&) -> eq_<Lhs_T, Rhs_T>;
406
-
407
370
  // ------------------------------------------------------------------------
408
371
 
409
372
  /**
410
- * @brief Non-equality comparator struct template.
373
+ * @brief Equality comparator struct template.
411
374
  *
412
375
  * @tparam Lhs_T The type of the left-hand operand.
413
376
  * @tparam Rhs_T The type of the right-hand operand.
414
377
  *
415
378
  * @details
416
- * The `ne_` struct template provides a type-safe mechanism for evaluating
417
- * non-equality between two operands within the framework.
379
+ * The `eq_` struct template provides a type-safe mechanism for evaluating
380
+ * equality between two operands within the framework.
418
381
  *
419
382
  * This comparator supports a variety of operand types, including those
420
383
  * with static values, types with precision (epsilon), and generic types.
@@ -428,32 +391,35 @@ namespace micro_os_plus::micro_test_plus
428
391
  * supports both compile-time and run-time evaluation.
429
392
  *
430
393
  * All definitions are intended for internal use within the framework and
431
- * are implemented in the `include/micro-os-plus` folder to maintain a
432
- * structured and modular codebase.
394
+ * are implemented in the `include/micro-os-plus/micro-test-plus` folder to
395
+ * maintain a structured and modular codebase.
433
396
  *
434
397
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
435
398
  */
436
399
  template <class Lhs_T, class Rhs_T>
437
- struct ne_ : type_traits::op
400
+ struct eq_ : binary_op_<Lhs_T, Rhs_T>
438
401
  {
439
402
  /**
440
- * @brief Constructs a non-equality comparator for the given operands.
403
+ * @brief Constructs an equality comparator for the given operands.
441
404
  *
442
405
  * @param lhs The left-hand operand.
443
406
  * @param rhs The right-hand operand.
444
407
  *
445
408
  * @details
446
- * Evaluates the non-equality of the provided operands at construction,
447
- * supporting static values, types with precision, and generic types. The
448
- * result is stored in the `value_` member for efficient access.
409
+ * Evaluates the equality of the provided operands and passes the
410
+ * result to the `binary_op_` base class constructor.
411
+ * Supports static values, types with precision, and generic types.
449
412
  */
450
- constexpr ne_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
451
- : lhs_{ lhs }, rhs_{ rhs }, value_{
452
- [&]
453
- {
454
- using std::operator==;
455
- using std::operator!=;
456
- using std::operator>;
413
+ constexpr eq_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
414
+ : binary_op_<Lhs_T, Rhs_T>{ lhs, rhs, [&]
415
+ {
416
+ // This lambda is called in the constructor to evaluate the
417
+ // comparison. Its result is implicitly converted to bool via
418
+ // the operator bool() of whatever type the branch returns.
419
+ // This is intentional: all result types (integral_constant,
420
+ // comparator objects, plain bool) define operator bool().
421
+ using std::operator==;
422
+ using std::operator<;
457
423
 
458
424
  #if defined(__GNUC__)
459
425
  #pragma GCC diagnostic push
@@ -466,130 +432,68 @@ namespace micro_os_plus::micro_test_plus
466
432
  #pragma clang diagnostic ignored "-Wpedantic"
467
433
  #endif
468
434
  #endif
469
- if constexpr (type_traits::has_value_v<Lhs_T>
470
- and type_traits::has_value_v<Rhs_T>)
471
- {
472
- return Lhs_T::value != Rhs_T::value;
473
- }
474
- else if constexpr (type_traits::has_epsilon_v<Lhs_T>
475
- and type_traits::has_epsilon_v<Rhs_T>)
476
- {
477
- return math::abs (get (lhs_) - get (rhs_))
478
- > math::min_value (Lhs_T::epsilon,
479
- Rhs_T::epsilon);
480
- }
481
- else if constexpr (type_traits::has_epsilon_v<Lhs_T>)
482
- {
483
- return math::abs (get (lhs_) - get (rhs_))
484
- > Lhs_T::epsilon;
485
- }
486
- else if constexpr (type_traits::has_epsilon_v<Rhs_T>)
487
- {
488
- return math::abs (get (lhs_) - get (rhs_))
489
- > Rhs_T::epsilon;
490
- }
491
- else
492
- {
493
- return get (lhs_) != get (rhs_);
494
- }
435
+ if constexpr (type_traits::has_value<Lhs_T>
436
+ and type_traits::has_value<Rhs_T>)
437
+ {
438
+ // If both types have values (like numeric constants),
439
+ // compare them directly.
440
+ return Lhs_T::value == Rhs_T::value;
441
+ }
442
+ else if constexpr (type_traits::has_epsilon<Lhs_T>
443
+ and type_traits::has_epsilon<Rhs_T>)
444
+ {
445
+ // If both values have precision, compare them using
446
+ // the smallest precision.
447
+ return math::abs (get (lhs) - get (rhs))
448
+ < math::min_value (lhs.epsilon, rhs.epsilon);
449
+ }
450
+ else if constexpr (type_traits::has_epsilon<Lhs_T>)
451
+ {
452
+ // If only the left operand has precision, use it.
453
+ return math::abs (get (lhs) - get (rhs)) < lhs.epsilon;
454
+ }
455
+ else if constexpr (type_traits::has_epsilon<Rhs_T>)
456
+ {
457
+ // If only the right operand has precision, use it.
458
+ return math::abs (get (lhs) - get (rhs)) < rhs.epsilon;
459
+ }
460
+ else
461
+ {
462
+ // Call the generic getters, which might
463
+ // either call the type get() or return the value.
464
+ return get (lhs) == get (rhs);
465
+ }
495
466
  #if defined(__GNUC__)
496
467
  #pragma GCC diagnostic pop
497
468
  #endif
498
- }()
499
- }
500
- {
501
- }
502
-
503
- /**
504
- * @brief Conversion operator to boolean.
505
- *
506
- * @par Parameters
507
- * None.
508
- * @retval true The operands are considered not equal.
509
- * @retval false The operands are considered equal.
510
- *
511
- * @details
512
- * Returns the result of the non-equality comparison.
513
- */
514
- [[nodiscard]] constexpr
515
- operator bool () const
516
- {
517
- return value_;
518
- }
519
-
520
- /**
521
- * @brief Retrieves the left-hand operand.
522
- *
523
- * @par Parameters
524
- * None.
525
- * @return The extracted left-hand operand.
526
- *
527
- * @details
528
- * Returns the value of the left-hand operand, applying the generic
529
- * getter to ensure correct extraction for both custom and standard
530
- * types.
531
- */
532
- [[nodiscard]] constexpr auto
533
- lhs (void) const
534
- {
535
- return get (lhs_);
536
- }
537
-
538
- /**
539
- * @brief Retrieves the right-hand operand.
540
- *
541
- * @par Parameters
542
- * None.
543
- * @return The extracted right-hand operand.
544
- *
545
- * @details
546
- * Returns the value of the right-hand operand, applying the generic
547
- * getter to ensure correct extraction for both custom and standard
548
- * types.
549
- */
550
- [[nodiscard]] constexpr auto
551
- rhs (void) const
469
+ }() }
552
470
  {
553
- return get (rhs_);
554
471
  }
555
-
556
- /**
557
- * @brief Stores the left-hand operand.
558
- */
559
- const Lhs_T lhs_{};
560
-
561
- /**
562
- * @brief Stores the right-hand operand.
563
- */
564
- const Rhs_T rhs_{};
565
-
566
- /**
567
- * @brief Stores the result of the non-equality comparison.
568
- */
569
- const bool value_{};
570
472
  };
571
473
 
572
474
  // Deduction guide.
573
475
  template <typename Lhs_T, typename Rhs_T>
574
- ne_ (const Lhs_T&, const Rhs_T&) -> ne_<Lhs_T, Rhs_T>;
476
+ eq_ (const Lhs_T&, const Rhs_T&) -> eq_<Lhs_T, Rhs_T>;
575
477
 
576
478
  // ------------------------------------------------------------------------
577
479
 
578
480
  /**
579
- * @brief Greater than comparator struct template.
481
+ * @brief Non-equality comparator struct template.
580
482
  *
581
483
  * @tparam Lhs_T The type of the left-hand operand.
582
484
  * @tparam Rhs_T The type of the right-hand operand.
583
485
  *
584
486
  * @details
585
- * The `gt_` struct template provides a type-safe mechanism for evaluating
586
- * whether the left-hand operand is greater than the right-hand operand
587
- * within the framework.
487
+ * The `ne_` struct template provides a type-safe mechanism for evaluating
488
+ * non-equality between two operands within the framework.
588
489
  *
589
490
  * This comparator supports a variety of operand types, including those
590
- * with static values and generic types. For types with static values, the
591
- * comparison is performed directly. For all other types, the generic
592
- * getter is used to retrieve and compare the values.
491
+ * with static values, types with precision (epsilon), and generic types.
492
+ * For types with static values, the comparison is performed directly. For
493
+ * types supporting precision, the comparison accounts for the smallest
494
+ * epsilon to ensure accuracy, particularly for floating-point types. For
495
+ * all other types, the generic getter is used to retrieve and compare the
496
+ * values.
593
497
  *
594
498
  * The implementation is optimised for use in embedded environments and
595
499
  * supports both compile-time and run-time evaluation.
@@ -601,27 +505,29 @@ namespace micro_os_plus::micro_test_plus
601
505
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
602
506
  */
603
507
  template <class Lhs_T, class Rhs_T>
604
- struct gt_ : type_traits::op
508
+ struct ne_ : binary_op_<Lhs_T, Rhs_T>
605
509
  {
606
510
  /**
607
- * @brief Constructs a greater than comparator for the given operands.
511
+ * @brief Constructs a non-equality comparator for the given operands.
608
512
  *
609
513
  * @param lhs The left-hand operand.
610
514
  * @param rhs The right-hand operand.
611
515
  *
612
516
  * @details
613
- * Evaluates whether the left-hand operand is greater than the right-hand
614
- * operand at construction, supporting static values and generic types.
615
- * The result is stored in the `value_` member for efficient access.
517
+ * Evaluates the non-equality of the provided operands and passes the
518
+ * result to the `binary_op_` base class constructor.
519
+ * Supports static values, types with precision, and generic types.
616
520
  */
617
- constexpr gt_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
618
- : lhs_{ lhs }, rhs_{ rhs },
619
- value_{ [&]
620
- {
621
- using std::operator>;
521
+ constexpr ne_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
522
+ : binary_op_<Lhs_T, Rhs_T>{ lhs, rhs, [&]
523
+ {
524
+ using std::operator==;
525
+ using std::operator!=;
526
+ using std::operator>;
622
527
 
623
528
  #if defined(__GNUC__)
624
529
  #pragma GCC diagnostic push
530
+ #pragma GCC diagnostic ignored "-Wfloat-equal"
625
531
  #pragma GCC diagnostic ignored "-Wconversion"
626
532
  #pragma GCC diagnostic ignored "-Wdouble-promotion"
627
533
  #pragma GCC diagnostic ignored "-Wsign-compare"
@@ -630,90 +536,113 @@ namespace micro_os_plus::micro_test_plus
630
536
  #pragma clang diagnostic ignored "-Wpedantic"
631
537
  #endif
632
538
  #endif
633
- if constexpr (type_traits::has_value_v<Lhs_T>
634
- and type_traits::has_value_v<Rhs_T>)
635
- {
636
- return Lhs_T::value > Rhs_T::value;
637
- }
638
- else
639
- {
640
- return get (lhs_) > get (rhs_);
641
- }
539
+ if constexpr (type_traits::has_value<Lhs_T>
540
+ and type_traits::has_value<Rhs_T>)
541
+ {
542
+ return Lhs_T::value != Rhs_T::value;
543
+ }
544
+ else if constexpr (type_traits::has_epsilon<Lhs_T>
545
+ and type_traits::has_epsilon<Rhs_T>)
546
+ {
547
+ return math::abs (get (lhs) - get (rhs))
548
+ >= math::min_value (lhs.epsilon, rhs.epsilon);
549
+ }
550
+ else if constexpr (type_traits::has_epsilon<Lhs_T>)
551
+ {
552
+ return math::abs (get (lhs) - get (rhs)) >= lhs.epsilon;
553
+ }
554
+ else if constexpr (type_traits::has_epsilon<Rhs_T>)
555
+ {
556
+ return math::abs (get (lhs) - get (rhs)) >= rhs.epsilon;
557
+ }
558
+ else
559
+ {
560
+ return get (lhs) != get (rhs);
561
+ }
642
562
  #if defined(__GNUC__)
643
563
  #pragma GCC diagnostic pop
644
564
  #endif
645
- }() }
565
+ }() }
646
566
  {
647
567
  }
568
+ };
648
569
 
649
- /**
650
- * @brief Conversion operator to boolean.
651
- *
652
- * @par Parameters
653
- * None.
654
- * @retval true The left-hand operand is greater than the right-hand
655
- * operand.
656
- * @retval false Otherwise.
657
- *
658
- * @details
659
- * Returns the result of the greater than comparison.
660
- */
661
- [[nodiscard]] constexpr
662
- operator bool () const
663
- {
664
- return value_;
665
- }
570
+ // Deduction guide.
571
+ template <typename Lhs_T, typename Rhs_T>
572
+ ne_ (const Lhs_T&, const Rhs_T&) -> ne_<Lhs_T, Rhs_T>;
666
573
 
667
- /**
668
- * @brief Retrieves the left-hand operand.
669
- *
670
- * @par Parameters
671
- * None.
672
- * @return The extracted left-hand operand.
673
- *
674
- * @details
675
- * Returns the value of the left-hand operand, applying the generic
676
- * getter to ensure correct extraction for both custom and standard
677
- * types.
678
- */
679
- [[nodiscard]] constexpr auto
680
- lhs (void) const
681
- {
682
- return get (lhs_);
683
- }
684
- [[nodiscard]] constexpr auto
574
+ // ------------------------------------------------------------------------
685
575
 
576
+ /**
577
+ * @brief Greater than comparator struct template.
578
+ *
579
+ * @tparam Lhs_T The type of the left-hand operand.
580
+ * @tparam Rhs_T The type of the right-hand operand.
581
+ *
582
+ * @details
583
+ * The `gt_` struct template provides a type-safe mechanism for evaluating
584
+ * whether the left-hand operand is greater than the right-hand operand
585
+ * within the framework.
586
+ *
587
+ * This comparator supports a variety of operand types, including those
588
+ * with static values and generic types. For types with static values, the
589
+ * comparison is performed directly. For all other types, the generic
590
+ * getter is used to retrieve and compare the values.
591
+ *
592
+ * The implementation is optimised for use in embedded environments and
593
+ * supports both compile-time and run-time evaluation.
594
+ *
595
+ * All definitions are intended for internal use within the framework and
596
+ * are implemented in the `include/micro-os-plus` folder to maintain a
597
+ * structured and modular codebase.
598
+ *
599
+ * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
600
+ */
601
+ template <class Lhs_T, class Rhs_T>
602
+ struct gt_ : binary_op_<Lhs_T, Rhs_T>
603
+ {
686
604
  /**
687
- * @brief Retrieves the right-hand operand.
605
+ * @brief Constructs a greater than comparator for the given operands.
688
606
  *
689
- * @par Parameters
690
- * None.
691
- * @return The extracted right-hand operand.
607
+ * @param lhs The left-hand operand.
608
+ * @param rhs The right-hand operand.
692
609
  *
693
610
  * @details
694
- * Returns the value of the right-hand operand, applying the generic
695
- * getter to ensure correct extraction for both custom and standard
696
- * types.
611
+ * Evaluates whether the left-hand operand is greater than the
612
+ * right-hand operand and passes the result to the `binary_op_` base
613
+ * class constructor.
614
+ * Supports static values and generic types.
697
615
  */
698
- rhs (void) const
616
+ constexpr gt_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
617
+ : binary_op_<Lhs_T, Rhs_T>{ lhs, rhs, [&]
618
+ {
619
+ using std::operator>;
620
+
621
+ #if defined(__GNUC__)
622
+ #pragma GCC diagnostic push
623
+ #pragma GCC diagnostic ignored "-Wconversion"
624
+ #pragma GCC diagnostic ignored "-Wdouble-promotion"
625
+ #pragma GCC diagnostic ignored "-Wsign-compare"
626
+ #if defined(__clang__)
627
+ #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
628
+ #pragma clang diagnostic ignored "-Wpedantic"
629
+ #endif
630
+ #endif
631
+ if constexpr (type_traits::has_value<Lhs_T>
632
+ and type_traits::has_value<Rhs_T>)
633
+ {
634
+ return Lhs_T::value > Rhs_T::value;
635
+ }
636
+ else
637
+ {
638
+ return get (lhs) > get (rhs);
639
+ }
640
+ #if defined(__GNUC__)
641
+ #pragma GCC diagnostic pop
642
+ #endif
643
+ }() }
699
644
  {
700
- return get (rhs_);
701
645
  }
702
-
703
- /**
704
- * @brief Stores the left-hand operand.
705
- */
706
- const Lhs_T lhs_{};
707
-
708
- /**
709
- * @brief Stores the right-hand operand.
710
- */
711
- const Rhs_T rhs_{};
712
-
713
- /**
714
- * @brief Stores the result of the greater than comparison.
715
- */
716
- const bool value_{};
717
646
  };
718
647
 
719
648
  // Deduction guide.
@@ -748,7 +677,7 @@ namespace micro_os_plus::micro_test_plus
748
677
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
749
678
  */
750
679
  template <class Lhs_T, class Rhs_T>
751
- struct ge_ : type_traits::op
680
+ struct ge_ : binary_op_<Lhs_T, Rhs_T>
752
681
  {
753
682
  /**
754
683
  * @brief Constructs a greater than or equal comparator for the given
@@ -758,16 +687,15 @@ namespace micro_os_plus::micro_test_plus
758
687
  * @param rhs The right-hand operand.
759
688
  *
760
689
  * @details
761
- * Evaluates whether the left-hand operand is greater than or equal to
762
- * the right-hand operand at construction, supporting static values and
763
- * generic types. The result is stored in the `value_` member for
764
- * efficient access.
690
+ * Evaluates whether the left-hand operand is greater than or equal
691
+ * to the right-hand operand and passes the result to the `binary_op_`
692
+ * base class constructor.
693
+ * Supports static values and generic types.
765
694
  */
766
695
  constexpr ge_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
767
- : lhs_{ lhs }, rhs_{ rhs },
768
- value_{ [&]
769
- {
770
- using std::operator>=;
696
+ : binary_op_<Lhs_T, Rhs_T>{ lhs, rhs, [&]
697
+ {
698
+ using std::operator>=;
771
699
 
772
700
  #if defined(__GNUC__)
773
701
  #pragma GCC diagnostic push
@@ -779,90 +707,21 @@ namespace micro_os_plus::micro_test_plus
779
707
  #pragma clang diagnostic ignored "-Wpedantic"
780
708
  #endif
781
709
  #endif
782
- if constexpr (type_traits::has_value_v<Lhs_T>
783
- and type_traits::has_value_v<Rhs_T>)
784
- {
785
- return Lhs_T::value >= Rhs_T::value;
786
- }
787
- else
788
- {
789
- return get (lhs_) >= get (rhs_);
790
- }
710
+ if constexpr (type_traits::has_value<Lhs_T>
711
+ and type_traits::has_value<Rhs_T>)
712
+ {
713
+ return Lhs_T::value >= Rhs_T::value;
714
+ }
715
+ else
716
+ {
717
+ return get (lhs) >= get (rhs);
718
+ }
791
719
  #if defined(__GNUC__)
792
720
  #pragma GCC diagnostic pop
793
721
  #endif
794
- }() }
795
- {
796
- }
797
-
798
- /**
799
- * @brief Conversion operator to boolean.
800
- *
801
- * @par Parameters
802
- * None.
803
- * @retval true The left-hand operand is greater than or equal to the
804
- * right-hand operand.
805
- * @retval false Otherwise.
806
- *
807
- * @details
808
- * Returns the result of the greater than or equal comparison.
809
- */
810
- [[nodiscard]] constexpr
811
- operator bool () const
812
- {
813
- return value_;
814
- }
815
-
816
- /**
817
- * @brief Retrieves the left-hand operand.
818
- *
819
- * @par Parameters
820
- * None.
821
- * @return The extracted left-hand operand.
822
- *
823
- * @details
824
- * Returns the value of the left-hand operand, applying the generic
825
- * getter to ensure correct extraction for both custom and standard
826
- * types.
827
- */
828
- [[nodiscard]] constexpr auto
829
- lhs (void) const
830
- {
831
- return get (lhs_);
832
- }
833
-
834
- /**
835
- * @brief Retrieves the right-hand operand.
836
- *
837
- * @par Parameters
838
- * None.
839
- * @return The extracted right-hand operand.
840
- *
841
- * @details
842
- * Returns the value of the right-hand operand, applying the generic
843
- * getter to ensure correct extraction for both custom and standard
844
- * types.
845
- */
846
- [[nodiscard]] constexpr auto
847
- rhs (void) const
722
+ }() }
848
723
  {
849
- return get (rhs_);
850
724
  }
851
-
852
- /**
853
- * @brief Stores the left-hand operand.
854
- */
855
- const Lhs_T lhs_{};
856
-
857
- /**
858
- * @brief Stores the right-hand operand.
859
- */
860
- const Rhs_T rhs_{};
861
-
862
- /**
863
- * @brief Stores the result of the greater than or equal comparison.
864
- */
865
- const bool value_{};
866
725
  };
867
726
 
868
727
  // Deduction guide.
@@ -897,7 +756,7 @@ namespace micro_os_plus::micro_test_plus
897
756
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
898
757
  */
899
758
  template <class Lhs_T, class Rhs_T>
900
- struct lt_ : type_traits::op
759
+ struct lt_ : binary_op_<Lhs_T, Rhs_T>
901
760
  {
902
761
  /**
903
762
  * @brief Constructs a less than comparator for the given operands.
@@ -907,14 +766,14 @@ namespace micro_os_plus::micro_test_plus
907
766
  *
908
767
  * @details
909
768
  * Evaluates whether the left-hand operand is less than the right-hand
910
- * operand at construction, supporting static values and generic types.
911
- * The result is stored in the `value_` member for efficient access.
769
+ * operand and passes the result to the `binary_op_` base class
770
+ * constructor.
771
+ * Supports static values and generic types.
912
772
  */
913
773
  constexpr lt_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
914
- : lhs_{ lhs }, rhs_{ rhs },
915
- value_{ [&]
916
- {
917
- using std::operator<;
774
+ : binary_op_<Lhs_T, Rhs_T>{ lhs, rhs, [&]
775
+ {
776
+ using std::operator<;
918
777
 
919
778
  #if defined(__GNUC__)
920
779
  #pragma GCC diagnostic push
@@ -926,91 +785,21 @@ namespace micro_os_plus::micro_test_plus
926
785
  #pragma clang diagnostic ignored "-Wpedantic"
927
786
  #endif
928
787
  #endif
929
- if constexpr (type_traits::has_value_v<Lhs_T>
930
- and type_traits::has_value_v<Rhs_T>)
931
- {
932
- return Lhs_T::value < Rhs_T::value;
933
- }
934
- else
935
- {
936
- return get (lhs_) < get (rhs_);
937
- }
788
+ if constexpr (type_traits::has_value<Lhs_T>
789
+ and type_traits::has_value<Rhs_T>)
790
+ {
791
+ return Lhs_T::value < Rhs_T::value;
792
+ }
793
+ else
794
+ {
795
+ return get (lhs) < get (rhs);
796
+ }
938
797
  #if defined(__GNUC__)
939
798
  #pragma GCC diagnostic pop
940
799
  #endif
941
- }() }
942
- {
943
- }
944
-
945
- /**
946
- * @brief Conversion operator to boolean.
947
- *
948
- * @par Parameters
949
- * None.
950
- * @retval true The left-hand operand is less than the right-hand
951
- * operand.
952
- * @retval false Otherwise.
953
- *
954
- * @details
955
- * Returns the result of the less than comparison.
956
- */
957
- [[nodiscard]] constexpr
958
- operator bool () const
959
- {
960
- return value_;
961
- }
962
-
963
- /**
964
- * @brief Retrieves the left-hand operand.
965
- *
966
- * @par Parameters
967
- * None.
968
- * @return The extracted left-hand operand.
969
- *
970
- * @details
971
- * Returns the value of the left-hand operand, applying the generic
972
- * getter to ensure correct extraction for both custom and standard
973
- * types.
974
- */
975
- [[nodiscard]] constexpr auto
976
- lhs (void) const
800
+ }() }
977
801
  {
978
- return get (lhs_);
979
802
  }
980
-
981
- /**
982
- * @brief Retrieves the right-hand operand.
983
- *
984
- * @par Parameters
985
- * None.
986
- * @return The extracted right-hand operand.
987
- *
988
- * @details
989
- * Returns the value of the right-hand operand, applying the generic
990
- * getter to ensure correct extraction for both custom and standard
991
- * types.
992
- */
993
- [[nodiscard]] constexpr auto
994
- rhs (void) const
995
- {
996
- return get (rhs_);
997
- }
998
-
999
- private:
1000
- /**
1001
- * @brief Stores the left-hand operand.
1002
- */
1003
- const Lhs_T lhs_{};
1004
-
1005
- /**
1006
- * @brief Stores the right-hand operand.
1007
- */
1008
- const Rhs_T rhs_{};
1009
-
1010
- /**
1011
- * @brief Stores the result of the less than comparison.
1012
- */
1013
- const bool value_{};
1014
803
  };
1015
804
 
1016
805
  // Deduction guide.
@@ -1045,7 +834,7 @@ namespace micro_os_plus::micro_test_plus
1045
834
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
1046
835
  */
1047
836
  template <class Lhs_T, class Rhs_T>
1048
- struct le_ : type_traits::op
837
+ struct le_ : binary_op_<Lhs_T, Rhs_T>
1049
838
  {
1050
839
  /**
1051
840
  * @brief Constructs a less than or equal comparator for the given
@@ -1055,16 +844,15 @@ namespace micro_os_plus::micro_test_plus
1055
844
  * @param rhs The right-hand operand.
1056
845
  *
1057
846
  * @details
1058
- * Evaluates whether the left-hand operand is less than or equal to the
1059
- * right-hand operand at construction, supporting static values and
1060
- * generic types. The result is stored in the `value_` member for
1061
- * efficient access.
847
+ * Evaluates whether the left-hand operand is less than or equal to
848
+ * the right-hand operand and passes the result to the `binary_op_` base
849
+ * class constructor.
850
+ * Supports static values and generic types.
1062
851
  */
1063
852
  constexpr le_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
1064
- : lhs_{ lhs }, rhs_{ rhs },
1065
- value_{ [&]
1066
- {
1067
- using std::operator<=;
853
+ : binary_op_<Lhs_T, Rhs_T>{ lhs, rhs, [&]
854
+ {
855
+ using std::operator<=;
1068
856
 
1069
857
  #if defined(__GNUC__)
1070
858
  #pragma GCC diagnostic push
@@ -1076,91 +864,21 @@ namespace micro_os_plus::micro_test_plus
1076
864
  #pragma clang diagnostic ignored "-Wpedantic"
1077
865
  #endif
1078
866
  #endif
1079
- if constexpr (type_traits::has_value_v<Lhs_T>
1080
- and type_traits::has_value_v<Rhs_T>)
1081
- {
1082
- return Lhs_T::value <= Rhs_T::value;
1083
- }
1084
- else
1085
- {
1086
- return get (lhs_) <= get (rhs_);
1087
- }
867
+ if constexpr (type_traits::has_value<Lhs_T>
868
+ and type_traits::has_value<Rhs_T>)
869
+ {
870
+ return Lhs_T::value <= Rhs_T::value;
871
+ }
872
+ else
873
+ {
874
+ return get (lhs) <= get (rhs);
875
+ }
1088
876
  #if defined(__GNUC__)
1089
877
  #pragma GCC diagnostic pop
1090
878
  #endif
1091
- }() }
1092
- {
1093
- }
1094
-
1095
- /**
1096
- * @brief Conversion operator to boolean.
1097
- *
1098
- * @par Parameters
1099
- * None.
1100
- * @retval true The left-hand operand is less than or equal to the
1101
- * right-hand operand.
1102
- * @retval false Otherwise.
1103
- *
1104
- * @details
1105
- * Returns the result of the less than or equal comparison.
1106
- */
1107
- [[nodiscard]] constexpr
1108
- operator bool () const
1109
- {
1110
- return value_;
1111
- }
1112
-
1113
- /**
1114
- * @brief Retrieves the left-hand operand.
1115
- *
1116
- * @par Parameters
1117
- * None.
1118
- * @return The extracted left-hand operand.
1119
- *
1120
- * @details
1121
- * Returns the value of the left-hand operand, applying the generic
1122
- * getter to ensure correct extraction for both custom and standard
1123
- * types.
1124
- */
1125
-
1126
- [[nodiscard]] constexpr auto
1127
- lhs (void) const
1128
- {
1129
- return get (lhs_);
1130
- }
1131
-
1132
- /**
1133
- * @brief Retrieves the right-hand operand.
1134
- *
1135
- * @par Parameters
1136
- * None.
1137
- * @return The extracted right-hand operand.
1138
- *
1139
- * @details
1140
- * Returns the value of the right-hand operand, applying the generic
1141
- * getter to ensure correct extraction for both custom and standard
1142
- * types.
1143
- */
1144
- [[nodiscard]] constexpr auto
1145
- rhs (void) const
879
+ }() }
1146
880
  {
1147
- return get (rhs_);
1148
881
  }
1149
-
1150
- /**
1151
- * @brief Stores the left-hand operand.
1152
- */
1153
- const Lhs_T lhs_{};
1154
-
1155
- /**
1156
- * @brief Stores the right-hand operand.
1157
- */
1158
- const Rhs_T rhs_{};
1159
-
1160
- /**
1161
- * @brief Stores the result of the less than or equal comparison.
1162
- */
1163
- const bool value_{};
1164
882
  };
1165
883
 
1166
884
  // Deduction guide.
@@ -1194,92 +912,24 @@ namespace micro_os_plus::micro_test_plus
1194
912
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
1195
913
  */
1196
914
  template <class Lhs_T, class Rhs_T>
1197
- struct and_ : type_traits::op
915
+ struct and_ : binary_op_<Lhs_T, Rhs_T>
1198
916
  {
1199
917
  /**
1200
918
  * @brief Constructs a logical AND comparator for the given operands.
1201
- *
1202
- * @param lhs The left-hand operand.
1203
- * @param rhs The right-hand operand.
1204
- *
1205
- * @details
1206
- * Evaluates the logical conjunction of the provided operands at
1207
- * construction, supporting both custom and standard types. The result is
1208
- * stored in the `value_` member for efficient access.
1209
- */
1210
- constexpr and_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
1211
- : lhs_{ lhs }, rhs_{ rhs },
1212
- value_{ static_cast<bool> (lhs) and static_cast<bool> (rhs) }
1213
- {
1214
- }
1215
-
1216
- /**
1217
- * @brief Conversion operator to boolean.
1218
- *
1219
- * @par Parameters
1220
- * None.
1221
- * @retval true Both operands evaluate to true.
1222
- * @retval false At least one operand evaluates to false.
1223
- *
1224
- * @details
1225
- * Returns the result of the logical AND operation.
1226
- */
1227
- [[nodiscard]] constexpr
1228
- operator bool () const
1229
- {
1230
- return value_;
1231
- }
1232
-
1233
- /**
1234
- * @brief Retrieves the left-hand operand.
1235
- *
1236
- * @par Parameters
1237
- * None.
1238
- * @return The extracted left-hand operand.
1239
- *
1240
- * @details
1241
- * Returns the value of the left-hand operand, applying the generic
1242
- * getter to ensure correct extraction for both custom and standard
1243
- * types.
1244
- */
1245
- [[nodiscard]] constexpr auto
1246
- lhs (void) const
1247
- {
1248
- return get (lhs_);
1249
- }
1250
-
1251
- /**
1252
- * @brief Retrieves the right-hand operand.
1253
- *
1254
- * @par Parameters
1255
- * None.
1256
- * @return The extracted right-hand operand.
1257
- *
1258
- * @details
1259
- * Returns the value of the right-hand operand, applying the generic
1260
- * getter to ensure correct extraction for both custom and standard
1261
- * types.
1262
- */
1263
- [[nodiscard]] constexpr auto
1264
- rhs (void) const
1265
- {
1266
- return get (rhs_);
1267
- }
1268
-
1269
- /**
1270
- * @brief Stores the left-hand operand.
1271
- */
1272
- const Lhs_T lhs_{};
1273
-
1274
- /**
1275
- * @brief Stores the right-hand operand.
1276
- */
1277
- const Rhs_T rhs_{};
1278
-
1279
- /**
1280
- * @brief Stores the result of the logical AND operation.
919
+ *
920
+ * @param lhs The left-hand operand.
921
+ * @param rhs The right-hand operand.
922
+ *
923
+ * @details
924
+ * Evaluates the logical conjunction of the provided operands and
925
+ * passes the result to the `binary_op_` base class constructor.
1281
926
  */
1282
- const bool value_{};
927
+ constexpr and_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
928
+ : binary_op_<Lhs_T, Rhs_T>{
929
+ lhs, rhs, static_cast<bool> (lhs) and static_cast<bool> (rhs)
930
+ }
931
+ {
932
+ }
1283
933
  };
1284
934
 
1285
935
  // Deduction guide.
@@ -1313,92 +963,24 @@ namespace micro_os_plus::micro_test_plus
1313
963
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
1314
964
  */
1315
965
  template <class Lhs_T, class Rhs_T>
1316
- struct or_ : type_traits::op
966
+ struct or_ : binary_op_<Lhs_T, Rhs_T>
1317
967
  {
1318
968
  /**
1319
969
  * @brief Constructs a logical OR comparator for the given operands.
1320
970
  *
1321
- * @details
1322
- * Evaluates the logical disjunction of the provided operands at
1323
- * construction, supporting both custom and standard types. The result is
1324
- * stored in the `value_` member for efficient access.
1325
- *
1326
971
  * @param lhs The left-hand operand.
1327
972
  * @param rhs The right-hand operand.
1328
- */
1329
- constexpr or_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
1330
- : lhs_{ lhs }, rhs_{ rhs },
1331
- value_{ static_cast<bool> (lhs) or static_cast<bool> (rhs) }
1332
- {
1333
- }
1334
-
1335
- /**
1336
- * @brief Conversion operator to boolean.
1337
- *
1338
- * @par Parameters
1339
- * None.
1340
- * @retval true At least one operand evaluates to true.
1341
- * @retval false Both operands evaluate to false.
1342
- *
1343
- * @details
1344
- * Returns the result of the logical OR operation.
1345
- */
1346
- [[nodiscard]] constexpr
1347
- operator bool () const
1348
- {
1349
- return value_;
1350
- }
1351
-
1352
- /**
1353
- * @brief Retrieves the left-hand operand.
1354
- *
1355
- * @par Parameters
1356
- * None.
1357
- * @return The extracted left-hand operand.
1358
- *
1359
- * @details
1360
- * Returns the value of the left-hand operand, applying the generic
1361
- * getter to ensure correct extraction for both custom and standard
1362
- * types.
1363
- */
1364
- [[nodiscard]] constexpr auto
1365
- lhs (void) const
1366
- {
1367
- return get (lhs_);
1368
- }
1369
-
1370
- /**
1371
- * @brief Retrieves the right-hand operand.
1372
- *
1373
- * @par Parameters
1374
- * None.
1375
- * @return The extracted right-hand operand.
1376
973
  *
1377
974
  * @details
1378
- * Returns the value of the right-hand operand, applying the generic
1379
- * getter to ensure correct extraction for both custom and standard
1380
- * types.
975
+ * Evaluates the logical disjunction of the provided operands and
976
+ * passes the result to the `binary_op_` base class constructor.
1381
977
  */
1382
- [[nodiscard]] constexpr auto
1383
- rhs (void) const
978
+ constexpr or_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
979
+ : binary_op_<Lhs_T, Rhs_T>{
980
+ lhs, rhs, static_cast<bool> (lhs) or static_cast<bool> (rhs)
981
+ }
1384
982
  {
1385
- return get (rhs_);
1386
983
  }
1387
-
1388
- /**
1389
- * @brief Stores the left-hand operand.
1390
- */
1391
- const Lhs_T lhs_{};
1392
-
1393
- /**
1394
- * @brief Stores the right-hand operand.
1395
- */
1396
- const Rhs_T rhs_{};
1397
-
1398
- /**
1399
- * @brief Stores the result of the logical OR operation.
1400
- */
1401
- const bool value_{};
1402
984
  };
1403
985
 
1404
986
  // Deduction guide.
@@ -1431,7 +1013,7 @@ namespace micro_os_plus::micro_test_plus
1431
1013
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
1432
1014
  */
1433
1015
  template <class T>
1434
- struct not_ : type_traits::op
1016
+ struct not_ : unary_op_<T>
1435
1017
  {
1436
1018
  /**
1437
1019
  * @brief Constructs a logical NOT comparator for the given operand.
@@ -1439,68 +1021,81 @@ namespace micro_os_plus::micro_test_plus
1439
1021
  * @param t The operand to be negated.
1440
1022
  *
1441
1023
  * @details
1442
- * Evaluates the logical negation of the provided operand at
1443
- * construction, supporting both custom and standard types. The result is
1444
- * stored in the `value_` member for efficient access.
1024
+ * Evaluates the logical negation of the provided operand and passes
1025
+ * the result to the `unary_op_` base class constructor.
1445
1026
  */
1446
1027
  explicit constexpr not_ (const T& t = {})
1447
- : t_{ t }, value_{ not static_cast<bool> (t) }
1028
+ : unary_op_<T>{ t, not static_cast<bool> (t) }
1448
1029
  {
1449
1030
  }
1031
+ };
1032
+
1033
+ // Deduction guide.
1034
+ template <typename T>
1035
+ not_ (const T&) -> not_<T>;
1036
+
1037
+ // ------------------------------------------------------------------------
1450
1038
 
1039
+ #if defined(__cpp_exceptions)
1040
+
1041
+ /**
1042
+ * @brief Common base struct for callable-wrapping operators.
1043
+ *
1044
+ * @details
1045
+ * The `callable_op_` struct provides the shared state and interface
1046
+ * for operator types that invoke a callable and reduce the outcome to
1047
+ * a single boolean result. It stores the result and exposes a
1048
+ * conversion operator, which is common to `throws_` and `nothrow_`.
1049
+ *
1050
+ * Unlike `unary_op_` and `binary_op_`, no template parameter is
1051
+ * needed because the callable itself is not retained after
1052
+ * construction.
1053
+ *
1054
+ * All definitions are intended for internal use within the framework
1055
+ * and are implemented in the
1056
+ * `include/micro-os-plus/micro-test-plus` folder to maintain a
1057
+ * structured and modular codebase.
1058
+ *
1059
+ * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
1060
+ */
1061
+ struct callable_op_ : type_traits::op
1062
+ {
1451
1063
  /**
1452
- * @brief Conversion operator to boolean.
1453
- *
1454
- * @par Parameters
1455
- * None.
1456
- * @retval true The operand evaluates to false.
1457
- * @retval false The operand evaluates to true.
1064
+ * @brief Constructs a callable operator with the pre-computed
1065
+ * boolean result.
1458
1066
  *
1459
- * @details
1460
- * Returns the result of the logical NOT operation.
1067
+ * @param value The pre-computed boolean result of the invocation.
1461
1068
  */
1462
- [[nodiscard]] constexpr
1463
- operator bool () const
1069
+ constexpr explicit callable_op_ (bool value) : value_{ value }
1464
1070
  {
1465
- return value_;
1466
1071
  }
1467
1072
 
1468
1073
  /**
1469
- * @brief Retrieves the value of the operand.
1074
+ * @brief Conversion operator to boolean.
1470
1075
  *
1471
1076
  * @par Parameters
1472
1077
  * None.
1473
- * @return The extracted operand value.
1078
+ * @return The result of the callable invocation.
1474
1079
  *
1475
1080
  * @details
1476
- * Returns the value of the operand, applying the generic getter to
1477
- * ensure correct extraction for both custom and standard types.
1081
+ * Returns the pre-computed boolean result stored by the derived
1082
+ * operator's constructor.
1478
1083
  */
1479
- [[nodiscard]] constexpr auto
1480
- value () const
1084
+ [[nodiscard]] constexpr
1085
+ operator bool () const
1481
1086
  {
1482
- return get (t_);
1087
+ return value_;
1483
1088
  }
1484
1089
 
1090
+ private:
1485
1091
  /**
1486
- * @brief Stores the operand.
1487
- */
1488
- const T t_{};
1489
-
1490
- /**
1491
- * @brief Stores the result of the logical NOT operation.
1092
+ * @brief Stores the result of the callable invocation.
1492
1093
  */
1493
1094
  const bool value_{};
1494
1095
  };
1495
1096
 
1496
- // Deduction guide.
1497
- template <typename T>
1498
- not_ (const T&) -> not_<T>;
1499
-
1500
1097
  // ------------------------------------------------------------------------
1501
1098
 
1502
- #if defined(__cpp_exceptions)
1503
-
1504
1099
  /**
1505
1100
  * @brief Operator struct template to check if an expression throws a
1506
1101
  * specific exception.
@@ -1528,7 +1123,7 @@ namespace micro_os_plus::micro_test_plus
1528
1123
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
1529
1124
  */
1530
1125
  template <class Callable_T, class Exception_T = void>
1531
- struct throws_ : type_traits::op
1126
+ struct throws_ : callable_op_
1532
1127
  {
1533
1128
  /**
1534
1129
  * @brief Constructs an exception checking operator for the given
@@ -1538,51 +1133,28 @@ namespace micro_os_plus::micro_test_plus
1538
1133
  *
1539
1134
  * @details
1540
1135
  * Invokes the provided callable and determines whether it throws an
1541
- * exception of the specified type. The result is stored in the `value_`
1542
- * member for efficient access.
1136
+ * exception of the specified type, then passes the result to the
1137
+ * `callable_op_` base class constructor.
1543
1138
  */
1544
1139
  constexpr explicit throws_ (const Callable_T& func)
1545
- : value_{ [&func]
1546
- {
1547
- try
1548
- {
1549
- func ();
1550
- }
1551
- catch (const Exception_T&)
1552
- {
1553
- return true;
1554
- }
1555
- catch (...)
1556
- {
1557
- return false;
1558
- }
1559
- return false;
1560
- }() }
1561
- {
1562
- }
1563
-
1564
- /**
1565
- * @brief Conversion operator to boolean.
1566
- *
1567
- * @par Parameters
1568
- * None.
1569
- * @retval true The callable throws the specified exception type.
1570
- * @retval false The callable does not throw the specified exception
1571
- * type.
1572
- *
1573
- * @details
1574
- * Returns the result of the exception check.
1575
- */
1576
- [[nodiscard]] constexpr
1577
- operator bool () const
1140
+ : callable_op_{ [&func]
1141
+ {
1142
+ try
1143
+ {
1144
+ func ();
1145
+ }
1146
+ catch (const Exception_T&)
1147
+ {
1148
+ return true;
1149
+ }
1150
+ catch (...)
1151
+ {
1152
+ return false;
1153
+ }
1154
+ return false;
1155
+ }() }
1578
1156
  {
1579
- return value_;
1580
1157
  }
1581
-
1582
- /**
1583
- * @brief Stores the result of the exception check.
1584
- */
1585
- const bool value_{};
1586
1158
  };
1587
1159
 
1588
1160
  // ------------------------------------------------------------------------
@@ -1612,7 +1184,7 @@ namespace micro_os_plus::micro_test_plus
1612
1184
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
1613
1185
  */
1614
1186
  template <class Callable_T>
1615
- struct throws_<Callable_T, void> : type_traits::op
1187
+ struct throws_<Callable_T, void> : callable_op_
1616
1188
  {
1617
1189
  /**
1618
1190
  * @brief Constructs an exception checking operator for the given
@@ -1620,48 +1192,26 @@ namespace micro_os_plus::micro_test_plus
1620
1192
  *
1621
1193
  * @details
1622
1194
  * Invokes the provided callable and determines whether it throws any
1623
- * exception. The result is stored in the `value_` member for efficient
1624
- * access.
1195
+ * exception, then passes the result to the `callable_op_` base
1196
+ * class constructor.
1625
1197
  *
1626
1198
  * @param func The callable object to be invoked.
1627
1199
  */
1628
1200
  constexpr explicit throws_ (const Callable_T& func)
1629
- : value_{ [&func]
1630
- {
1631
- try
1632
- {
1633
- func ();
1634
- }
1635
- catch (...)
1636
- {
1637
- return true;
1638
- }
1639
- return false;
1640
- }() }
1641
- {
1642
- }
1643
-
1644
- /**
1645
- * @brief Conversion operator to boolean.
1646
- *
1647
- * @par Parameters
1648
- * None.
1649
- * @retval true The callable throws an exception.
1650
- *
1651
- * @details
1652
- * Returns the result of the exception check.
1653
- * @retval false The callable does not throw any exception.
1654
- */
1655
- [[nodiscard]] constexpr
1656
- operator bool () const
1201
+ : callable_op_{ [&func]
1202
+ {
1203
+ try
1204
+ {
1205
+ func ();
1206
+ }
1207
+ catch (...)
1208
+ {
1209
+ return true;
1210
+ }
1211
+ return false;
1212
+ }() }
1657
1213
  {
1658
- return value_;
1659
1214
  }
1660
-
1661
- /**
1662
- * @brief Stores the result of the exception check.
1663
- */
1664
- const bool value_{};
1665
1215
  };
1666
1216
 
1667
1217
  // ------------------------------------------------------------------------
@@ -1691,203 +1241,39 @@ namespace micro_os_plus::micro_test_plus
1691
1241
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
1692
1242
  */
1693
1243
  template <class Callable_T>
1694
- struct nothrow_ : type_traits::op
1244
+ struct nothrow_ : callable_op_
1695
1245
  {
1696
1246
  /**
1697
- * @brief Constructs a nothrow checking operator for the given callable.
1247
+ * @brief Constructs a nothrow checking operator for the given
1248
+ * callable.
1698
1249
  *
1699
1250
  * @param func The callable object to be invoked.
1700
1251
  *
1701
1252
  * @details
1702
1253
  * Invokes the provided callable and determines whether it completes
1703
- * without throwing any exception. The result is stored in the `value_`
1704
- * member for efficient access.
1254
+ * without throwing any exception, then passes the result to the
1255
+ * `callable_op_` base class constructor.
1705
1256
  */
1706
1257
  constexpr explicit nothrow_ (const Callable_T& func)
1707
- : value_{ [&func]
1708
- {
1709
- try
1710
- {
1711
- func ();
1712
- }
1713
- catch (...)
1714
- {
1715
- return false;
1716
- }
1717
- return true;
1718
- }() }
1719
- {
1720
- }
1721
-
1722
- /**
1723
- * @brief Conversion operator to boolean.
1724
- *
1725
- * @par Parameters
1726
- * None.
1727
- * @retval true The callable does not throw any exception.
1728
- * @retval false The callable throws an exception.
1729
- *
1730
- * @details
1731
- * Returns the result of the nothrow check.
1732
- */
1733
- [[nodiscard]] constexpr
1734
- operator bool () const
1258
+ : callable_op_{ [&func]
1259
+ {
1260
+ try
1261
+ {
1262
+ func ();
1263
+ }
1264
+ catch (...)
1265
+ {
1266
+ return false;
1267
+ }
1268
+ return true;
1269
+ }() }
1735
1270
  {
1736
- return value_;
1737
1271
  }
1738
-
1739
- /**
1740
- * @brief Stores the result of the nothrow check.
1741
- */
1742
- const bool value_{};
1743
1272
  };
1744
1273
 
1745
1274
  #endif
1746
1275
 
1747
1276
  // ------------------------------------------------------------------------
1748
-
1749
- /**
1750
- * @brief Base class for a deferred reporter that collects messages into a
1751
- * string.
1752
- *
1753
- * @details
1754
- * The `deferred_reporter_base` class serves as the foundational component
1755
- * for deferred reporting within the framework. It is responsible for
1756
- * collecting expectation messages, typically passed via the
1757
- * `operator<<()`, into a string for later reporting.
1758
- *
1759
- * This class maintains the result value, abort status, and the source
1760
- * location associated with the report. It is intended exclusively for
1761
- * internal use and is implemented in the
1762
- * `include/micro-os-plus/micro-test-plus` folder to ensure a structured
1763
- * and modular codebase.
1764
- *
1765
- * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
1766
- */
1767
- class deferred_reporter_base
1768
- {
1769
- public:
1770
- /**
1771
- * @brief Constructs a deferred reporter base.
1772
- *
1773
- * @param value The result value associated with the report.
1774
- * @param location The source location relevant to the report.
1775
- */
1776
- deferred_reporter_base (bool value,
1777
- const reflection::source_location location);
1778
-
1779
- /**
1780
- * @brief Destructor for the deferred reporter base.
1781
- */
1782
- ~deferred_reporter_base ();
1783
-
1784
- /**
1785
- * @brief Appends a message to the reporter.
1786
- *
1787
- * @tparam T The type of the message to append.
1788
- *
1789
- * @param msg The message to append.
1790
- * @return Reference to the current reporter instance.
1791
- */
1792
- template <class T>
1793
- auto&
1794
- operator<< (const T& msg);
1795
-
1796
- /**
1797
- * @brief Retrieves the result value.
1798
- *
1799
- *
1800
- * @par Parameters
1801
- * None.
1802
- * @retval true The reported condition was met.
1803
- * @retval false The reported condition was not met.
1804
- *
1805
- * @details
1806
- * Returns the result value associated with the report.
1807
- */
1808
- [[nodiscard]] constexpr bool
1809
- value () const
1810
- {
1811
- return value_;
1812
- }
1813
-
1814
- protected:
1815
- /**
1816
- * @brief Stores the result value of the report.
1817
- */
1818
- bool value_{};
1819
-
1820
- /**
1821
- * @brief Indicates whether the reporting should abort further
1822
- * processing.
1823
- */
1824
- bool abort_ = false;
1825
-
1826
- /**
1827
- * @brief Stores the source location associated with the report.
1828
- */
1829
- const reflection::source_location location_{};
1830
-
1831
- /**
1832
- * @brief String to collect the expectation message passed via
1833
- * `operator<<()`.
1834
- */
1835
- std::string message_{};
1836
- };
1837
-
1838
- // ------------------------------------------------------------------------
1839
-
1840
- /**
1841
- * @brief Deferred reporter class template for a specific expression.
1842
- *
1843
- * @tparam Expr_T The type of the expression being reported.
1844
- *
1845
- * @details
1846
- * The `deferred_reporter` class template extends `deferred_reporter_base`
1847
- * to provide deferred reporting functionality for a specific test
1848
- * expression within the framework.
1849
- *
1850
- * This class template is responsible for capturing the expression under
1851
- * evaluation, the abort status, and the source location. It is intended
1852
- * exclusively for internal use and is implemented in the
1853
- * `include/micro-os-plus/micro-test-plus` folder to ensure a structured
1854
- * and modular codebase.
1855
- *
1856
- * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
1857
- */
1858
- template <class Expr_T>
1859
- class deferred_reporter : public deferred_reporter_base
1860
- {
1861
- public:
1862
- /**
1863
- * @brief Constructs a deferred reporter for a specific expression.
1864
- *
1865
- * @param expr The expression under evaluation.
1866
- * @param abort Indicates whether reporting should abort further
1867
- * processing.
1868
- * @param location The source location relevant to the report.
1869
- *
1870
- * @details
1871
- * Initialises the reporter with the given expression, abort status, and
1872
- * source location.
1873
- */
1874
- constexpr explicit deferred_reporter (
1875
- const Expr_T& expr, bool abort,
1876
- const reflection::source_location& location);
1877
-
1878
- /**
1879
- * @brief Destructor for the deferred reporter.
1880
- */
1881
- ~deferred_reporter ();
1882
-
1883
- protected:
1884
- /**
1885
- * @brief Stores the expression under evaluation.
1886
- */
1887
- const Expr_T expr_{};
1888
- };
1889
-
1890
- // ------------------------------------------------------------------------
1891
1277
  } // namespace detail
1892
1278
 
1893
1279
  // --------------------------------------------------------------------------