@micro-os-plus/micro-test-plus 3.3.1 → 4.1.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 (65) hide show
  1. package/CHANGELOG.md +412 -2
  2. package/CMakeLists.txt +134 -28
  3. package/README.md +3 -2
  4. package/config/xcdl-build.json +11 -4
  5. package/include/micro-os-plus/micro-test-plus/README.md +6 -0
  6. package/include/micro-os-plus/micro-test-plus/deferred-reporter.h +267 -0
  7. package/include/micro-os-plus/micro-test-plus/detail.h +272 -1425
  8. package/include/micro-os-plus/micro-test-plus/exceptions.h +125 -0
  9. package/include/micro-os-plus/micro-test-plus/expression-formatter.h +669 -0
  10. package/include/micro-os-plus/micro-test-plus/function-comparators.h +15 -7
  11. package/include/micro-os-plus/micro-test-plus/inlines/{details-inlines.h → deferred-reporter-inlines.h} +66 -44
  12. package/include/micro-os-plus/micro-test-plus/inlines/detail-inlines.h +711 -0
  13. package/include/micro-os-plus/micro-test-plus/inlines/exceptions-inline.h +137 -0
  14. package/include/micro-os-plus/micro-test-plus/inlines/{test-reporter-inlines.h → expression-formatter-inlines.h} +232 -198
  15. package/include/micro-os-plus/micro-test-plus/inlines/function-comparators-inlines.h +24 -20
  16. package/include/micro-os-plus/micro-test-plus/inlines/literals-inlines.h +50 -31
  17. package/include/micro-os-plus/micro-test-plus/inlines/math-inlines.h +25 -19
  18. package/include/micro-os-plus/micro-test-plus/inlines/operators-inlines.h +275 -0
  19. package/include/micro-os-plus/micro-test-plus/inlines/reflection-inlines.h +39 -21
  20. package/include/micro-os-plus/micro-test-plus/inlines/reporter-inlines.h +205 -0
  21. package/include/micro-os-plus/micro-test-plus/inlines/runner-inlines.h +151 -0
  22. package/include/micro-os-plus/micro-test-plus/inlines/runner-totals-inlines.h +152 -0
  23. package/include/micro-os-plus/micro-test-plus/inlines/test-inlines.h +555 -0
  24. package/include/micro-os-plus/micro-test-plus/inlines/timings-inlines.h +120 -0
  25. package/include/micro-os-plus/micro-test-plus/inlines/type-traits-inlines.h +231 -0
  26. package/include/micro-os-plus/micro-test-plus/inlines/utility-inlines.h +126 -0
  27. package/include/micro-os-plus/micro-test-plus/literals.h +12 -17
  28. package/include/micro-os-plus/micro-test-plus/math.h +14 -6
  29. package/include/micro-os-plus/micro-test-plus/operators.h +53 -209
  30. package/include/micro-os-plus/micro-test-plus/reflection.h +8 -4
  31. package/include/micro-os-plus/micro-test-plus/{test-reporter-basic.h → reporter-human.h} +80 -74
  32. package/include/micro-os-plus/micro-test-plus/{test-reporter-tap.h → reporter-tap.h} +77 -71
  33. package/include/micro-os-plus/micro-test-plus/reporter.h +619 -0
  34. package/include/micro-os-plus/micro-test-plus/runner-totals.h +250 -0
  35. package/include/micro-os-plus/micro-test-plus/runner.h +472 -0
  36. package/include/micro-os-plus/micro-test-plus/test.h +1013 -0
  37. package/include/micro-os-plus/micro-test-plus/timings.h +363 -0
  38. package/include/micro-os-plus/micro-test-plus/type-traits.h +223 -577
  39. package/include/micro-os-plus/micro-test-plus/utility.h +136 -0
  40. package/include/micro-os-plus/micro-test-plus.h +42 -236
  41. package/meson.build +11 -6
  42. package/package.json +11 -3
  43. package/src/deferred-reporter.cpp +137 -0
  44. package/src/expression-formatter.cpp +289 -0
  45. package/src/reflection.cpp +97 -0
  46. package/src/reporter-human.cpp +816 -0
  47. package/src/reporter-tap.cpp +772 -0
  48. package/src/reporter.cpp +481 -0
  49. package/src/runner-totals.cpp +98 -0
  50. package/src/runner.cpp +669 -0
  51. package/src/test.cpp +503 -0
  52. package/src/timings.cpp +210 -0
  53. package/src/utility.cpp +163 -0
  54. package/.cmake-format.yaml +0 -11
  55. package/include/micro-os-plus/micro-test-plus/inlines/micro-test-plus-inlines.h +0 -313
  56. package/include/micro-os-plus/micro-test-plus/inlines/test-suite-inlines.h +0 -115
  57. package/include/micro-os-plus/micro-test-plus/test-reporter.h +0 -846
  58. package/include/micro-os-plus/micro-test-plus/test-runner.h +0 -281
  59. package/include/micro-os-plus/micro-test-plus/test-suite.h +0 -492
  60. package/src/micro-test-plus.cpp +0 -316
  61. package/src/test-reporter-basic.cpp +0 -466
  62. package/src/test-reporter-tap.cpp +0 -530
  63. package/src/test-reporter.cpp +0 -399
  64. package/src/test-runner.cpp +0 -311
  65. package/src/test-suite.cpp +0 -304
@@ -54,6 +54,9 @@
54
54
 
55
55
  // ----------------------------------------------------------------------------
56
56
 
57
+ #include <string_view>
58
+ #include <type_traits>
59
+
57
60
  #include "math.h"
58
61
 
59
62
  // ----------------------------------------------------------------------------
@@ -66,6 +69,8 @@
66
69
  #endif
67
70
  #endif
68
71
 
72
+ // ============================================================================
73
+
69
74
  namespace micro_os_plus::micro_test_plus
70
75
  {
71
76
  // --------------------------------------------------------------------------
@@ -83,7 +88,7 @@ namespace micro_os_plus::micro_test_plus
83
88
  * This includes templates for function traits, type lists, identity, value
84
89
  * wrappers, and compile-time checks for container types, floating point
85
90
  * types, and type convertibility. It also provides generic integral and
86
- * floating point constant wrappers, as well as mechanisms for SFINAE and
91
+ * floating point constant wrappers, as well as C++20 concepts and
87
92
  * requirements checking.
88
93
  *
89
94
  * These utilities facilitate advanced template programming, type deduction,
@@ -123,7 +128,10 @@ namespace micro_os_plus::micro_test_plus
123
128
  * @brief Struct template for compile-time type identity.
124
129
  *
125
130
  * @tparam T The type to be preserved.
126
- * @tparam Extra Additional template parameters, ignored.
131
+ * @tparam Extra Additional template parameters, ignored. The variadic
132
+ * `Extra` parameter pack absorbs additional type arguments that may
133
+ * arise during template argument deduction in some metaprogramming
134
+ * contexts, preventing substitution failures.
127
135
  *
128
136
  * @details
129
137
  * The `identity` struct template provides a mechanism for preserving a
@@ -132,8 +140,8 @@ namespace micro_os_plus::micro_test_plus
132
140
  * within the µTest++ framework.
133
141
  *
134
142
  * This utility is particularly useful in scenarios where type deduction or
135
- * SFINAE is required, as it allows the type to be carried through template
136
- * specialisations without modification.
143
+ * concept constraints are required, as it allows the type to be carried
144
+ * through template specialisations without modification.
137
145
  *
138
146
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
139
147
  */
@@ -314,369 +322,226 @@ namespace micro_os_plus::micro_test_plus
314
322
  using args = list<Args_T...>;
315
323
  };
316
324
 
317
- /**
318
- * @brief Utility function template to simulate std::declval for type
319
- * deduction.
320
- *
321
- * @tparam T The type for which an rvalue reference is required.
322
- *
323
- * @par Parameters
324
- * None.
325
- * @return An rvalue reference to type `T`.
326
- *
327
- * @details
328
- * The `declval` function template provides a mechanism for obtaining an
329
- * rvalue reference to a type `T` without requiring an actual object. This
330
- * is primarily used in unevaluated contexts, such as within `decltype`, to
331
- * deduce types during template metaprogramming in the µTest++ framework.
332
- */
333
- template <class T>
334
- T&&
335
- declval (void);
336
- template <class... Ts, class Expr_T>
337
- constexpr auto
338
- is_valid (Expr_T expr) -> decltype (expr (declval<Ts...> ()), bool ())
339
- {
340
- return true;
341
- }
325
+ // ------------------------------------------------------------------------
342
326
 
343
327
  /**
344
- * @brief Fallback function template for is_valid, returns false if the
345
- * expression is not valid.
328
+ * @brief Empty base struct for all operator types.
346
329
  *
347
- * @tparam Ts The argument types to be tested.
330
+ * @details
331
+ * The `op` struct serves as a common base for all operator and value
332
+ * wrapper types used in the µTest++ framework's type traits and
333
+ * metaprogramming utilities. It provides a unified type hierarchy,
334
+ * enabling compile-time detection and generic handling of operator-like
335
+ * types within the framework.
348
336
  *
349
- * @return `false` indicating the expression is not valid for the given
350
- * argument types.
337
+ * This struct is intended for internal use as a base for integral
338
+ * constants, floating point constants, and other value wrappers,
339
+ * supporting advanced template metaprogramming and type introspection.
351
340
  *
352
- * @details
353
- * This overload is selected when the primary `is_valid` template cannot be
354
- * instantiated, providing a `false` result for invalid expressions.
341
+ * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
355
342
  */
356
- template <class... Ts>
357
- constexpr auto
358
- is_valid (...) -> bool
343
+ struct op
359
344
  {
360
- return false;
361
- }
345
+ };
346
+
347
+ // ------------------------------------------------------------------------
348
+ // Concepts.
362
349
 
363
350
  /**
364
- * @brief Variable template to determine if a type models a container.
365
- *
366
- * @tparam T The type to be checked for container-like behaviour.
351
+ * @brief C++20 concept satisfied when `T` provides both `begin()` and
352
+ * `end()` member functions.
367
353
  *
368
- * @retval true if `T` has both `begin()` and `end()` member functions.
369
- * @retval false otherwise.
354
+ * @tparam T The type to be checked.
370
355
  *
371
356
  * @details
372
- * The `is_container_v` variable template evaluates to `true` if the given
373
- * type `T` provides both `begin()` and `end()` member functions,
374
- * indicating that it models a standard container concept. This trait is
375
- * determined at compile time using SFINAE and is_valid, and is used
376
- * throughout the µTest++ framework to enable generic handling of container
377
- * types in template metaprogramming.
357
+ * The `container_like` concept is satisfied when `T` exposes both a
358
+ * `begin()` and an `end()` member function, as required by standard
359
+ * range-based iteration. It is used to detect container types for
360
+ * specialised comparison and reporting within the framework.
378
361
  */
379
362
  template <class T>
380
- static constexpr auto is_container_v = is_valid<T> (
381
- [] (auto t) -> decltype (t.begin (), t.end (), void ()) {});
363
+ concept container_like = requires (const T& t) {
364
+ t.begin ();
365
+ t.end ();
366
+ };
382
367
 
383
368
  /**
384
- * @brief Variable template to determine if a type provides a static `npos`
385
- * member.
386
- *
387
- * @tparam T The type to be checked for the presence of a static `npos`
388
- * member.
369
+ * @brief C++20 concept satisfied when `T` provides a `npos` member.
389
370
  *
390
- * @retval true if `T` has a static member named `npos`.
391
- * @retval false otherwise.
371
+ * @tparam T The type to be checked.
392
372
  *
393
373
  * @details
394
- * The `has_npos_v` variable template evaluates to `true` if the given type
395
- * `T` defines a static member named `npos`. This trait is determined at
396
- * compile time using SFINAE and the `is_valid` utility, and is used
397
- * throughout the µTest++ framework to enable generic handling of types
398
- * that follow the standard string or container conventions.
374
+ * The `has_npos` concept is satisfied when `T` exposes a static `npos`
375
+ * member, as provided by `std::string_view` and similar types. It is
376
+ * used to detect string-like types for specialised comparison and
377
+ * reporting within the framework.
399
378
  */
400
379
  template <class T>
401
- static constexpr auto has_npos_v
402
- = is_valid<T> ([] (auto t) -> decltype (void (t.npos)) {});
380
+ concept has_npos = requires { T::npos; };
403
381
 
404
382
  /**
405
- * @brief Variable template to determine if a type provides a `value`
406
- * member.
407
- *
408
- * @tparam T The type to be checked for the presence of a `value` member.
383
+ * @brief C++20 concept satisfied when `T` provides a `value` member.
409
384
  *
410
- * @retval true if `T` has a member named `value`.
411
- * @retval false otherwise.
385
+ * @tparam T The type to be checked.
412
386
  *
413
387
  * @details
414
- * The `has_value_v` variable template evaluates to `true` if the given
415
- * type `T` defines a member named `value`. This trait is determined at
416
- * compile time using SFINAE and the `is_valid` utility, and is used
417
- * throughout the µTest++ framework to enable generic handling of types
418
- * that encapsulate a value, such as wrappers or constant types.
388
+ * The `has_value` concept is satisfied when an instance of `T` exposes
389
+ * a `value` member. It is used to detect framework value-wrapper types
390
+ * such as `integral_constant`, `floating_point_constant`, and `value<T>`,
391
+ * enabling specialised comparison and reporting.
419
392
  */
420
393
  template <class T>
421
- static constexpr auto has_value_v
422
- = is_valid<T> ([] (auto t) -> decltype (void (t.value)) {});
394
+ concept has_value = requires (const T& t) { t.value; };
423
395
 
424
396
  /**
425
- * @brief Variable template to determine if a type provides an `epsilon`
426
- * member.
397
+ * @brief C++20 concept satisfied when `T` provides an `epsilon` member.
427
398
  *
428
- * @tparam T The type to be checked for the presence of an `epsilon`
429
- * member.
430
- *
431
- * @retval true if `T` has a member named `epsilon`.
432
- * @retval false otherwise.
399
+ * @tparam T The type to be checked.
433
400
  *
434
401
  * @details
435
- * The `has_epsilon_v` variable template evaluates to `true` if the given
436
- * type `T` defines a member named `epsilon`. This trait is determined at
437
- * compile time using SFINAE and the `is_valid` utility, and is used
438
- * throughout the µTest++ framework to enable generic handling of types
439
- * that represent floating-point values or require precision control.
402
+ * The `has_epsilon` concept is satisfied when an instance of `T` exposes
403
+ * an `epsilon` member. It is used to detect floating point value-wrapper
404
+ * types such as `floating_point_constant` and the floating point
405
+ * specialisation of `value<T>`, enabling precision-aware comparisons.
440
406
  */
441
407
  template <class T>
442
- static constexpr auto has_epsilon_v
443
- = is_valid<T> ([] (auto t) -> decltype (void (t.epsilon)) {});
408
+ concept has_epsilon = requires (const T& t) { t.epsilon; };
444
409
 
445
410
  /**
446
- * @brief Variable template to determine if a type is a floating point
411
+ * @brief C++20 concept satisfied when `T` is a standard floating point
447
412
  * type.
448
413
  *
449
- * @tparam T The type to be checked for floating point classification.
450
- *
451
- * @retval true if `T` is a floating point type.
452
- * @retval false otherwise.
414
+ * @tparam T The type to be checked.
453
415
  *
454
416
  * @details
455
- * The `is_floating_point_v` variable template evaluates to `true` if the
456
- * given type `T` is a floating point type (`float`, `double`, or `long
457
- * double`). For all other types, it evaluates to `false`. This trait is
458
- * used throughout the µTest++ framework to enable type-safe handling and
459
- * specialisation for floating point types in template metaprogramming.
460
- *
461
- * Specialisations are provided for `float`, `double`, and `long double`,
462
- * each evaluating to `true`.
417
+ * The `is_floating_point` concept is satisfied when `T` is one of the
418
+ * standard floating point types (`float`, `double`, or `long double`).
419
+ * It is the primary definition; `is_floating_point_v` is derived from
420
+ * it for use in `if constexpr` and non-concept contexts.
463
421
  */
464
422
  template <class T>
465
- inline constexpr auto is_floating_point_v = false;
466
-
467
- /**
468
- * @brief Variable template specialisation indicating that `float` is a
469
- * floating point type.
470
- *
471
- * @details
472
- * This specialisation of the `is_floating_point_v` variable template
473
- * evaluates to `true` for the `float` type, confirming that it is
474
- * recognised as a floating point type within the µTest++ framework. This
475
- * enables type-safe handling and specialisation for floating point types
476
- * in template metaprogramming.
477
- *
478
- * @see is_floating_point_v
479
- */
480
- template <>
481
- inline constexpr auto is_floating_point_v<float> = true;
423
+ concept is_floating_point = std::is_floating_point_v<T>;
482
424
 
483
425
  /**
484
- * @brief Variable template specialisation indicating that `double` is a
485
- * floating point type.
426
+ * @brief C++20 concept satisfied when a type derives from `op`.
486
427
  *
487
- * @details
488
- * This specialisation of the `is_floating_point_v` variable template
489
- * evaluates to `true` for the `double` type, confirming that it is
490
- * recognised as a floating point type within the µTest++ framework. This
491
- * enables type-safe handling and specialisation for floating point types
492
- * in template metaprogramming.
493
- *
494
- * @see is_floating_point_v
495
- */
496
- template <>
497
- inline constexpr auto is_floating_point_v<double> = true;
498
-
499
- /**
500
- * @brief Variable template specialisation indicating that `long double` is
501
- * a floating point type.
428
+ * @tparam T The type to be checked.
502
429
  *
503
430
  * @details
504
- * This specialisation of the `is_floating_point_v` variable template
505
- * evaluates to `true` for the `long double` type, confirming that it is
506
- * recognised as a floating point type within the µTest++ framework. This
507
- * enables type-safe handling and specialisation for floating point types
508
- * in template metaprogramming.
509
- *
510
- * @see is_floating_point_v
431
+ * The `is_op` concept is satisfied when `T` is derived from the
432
+ * `type_traits::op` base struct. It is the primary definition used
433
+ * throughout the framework; `is_op_v` is derived from it for use in
434
+ * `if constexpr` and boolean contexts.
511
435
  */
512
- template <>
513
- inline constexpr auto is_floating_point_v<long double> = true;
436
+ template <class T>
437
+ concept is_op = std::is_base_of_v<type_traits::op, T>;
514
438
 
515
- #if defined(__clang__) or defined(_MSC_VER)
516
439
  /**
517
- * @brief Variable template to determine if one type is convertible to
518
- * another.
519
- *
520
- * @tparam From The source type to be checked for convertibility.
521
- * @tparam To The target type to which conversion is tested.
440
+ * @brief C++20 concept satisfied when at least one of two types derives
441
+ * from `op`.
522
442
  *
523
- * @retval true if `From` is convertible to `To`.
524
- * @retval false otherwise.
443
+ * @tparam Lhs_T The type of the left-hand operand.
444
+ * @tparam Rhs_T The type of the right-hand operand.
525
445
  *
526
446
  * @details
527
- * The `is_convertible_v` variable template evaluates to `true` if the type
528
- * `From` is implicitly convertible to the type `To`, and `false`
529
- * otherwise. This trait is determined at compile time and is used
530
- * throughout the µTest++ framework to enable type-safe conversions and
531
- * requirements checking in template metaprogramming.
532
- *
533
- * On supported compilers, this trait leverages compiler intrinsics for
534
- * optimal performance and accuracy.
447
+ * The `any_op` concept is satisfied when `Lhs_T` or `Rhs_T` (or both)
448
+ * are derived from the `type_traits::op` base struct. It is used to
449
+ * constrain binary operator overloads in the `operators` namespace so
450
+ * that they are enabled only when at least one operand is a framework
451
+ * type, avoiding unintended conflicts with user-defined operators.
535
452
  */
536
- template <class From, class To>
537
- static constexpr auto is_convertible_v = __is_convertible_to (From, To);
538
- #else
539
- /**
540
- * @brief Function template to determine if one type is convertible to
541
- * another.
542
- *
543
- * @tparam From The source type to be checked for convertibility.
544
- * @tparam To The target type to which conversion is tested.
545
- *
546
- * @param n Dummy parameter used for overload resolution.
547
- * @retval true if `From` is convertible to `To`.
548
- *
549
- * @details
550
- * The `is_convertible` function template checks, at compile time, whether
551
- * a value of type `From` can be implicitly converted to type `To`. This is
552
- * achieved using SFINAE and is primarily used as an implementation detail
553
- * for the `is_convertible_v` variable template within the µTest++
554
- * framework.
555
- *
556
- * If the conversion is valid, this overload is selected and returns
557
- * `true`.
558
- */
559
- template <class From, class To>
560
- constexpr auto
561
- is_convertible (int n) -> decltype (bool (To (declval<From> ())))
562
- {
563
- (void)n; // Prevent the unused parameter warning.
564
- return true;
565
- }
453
+ template <class Lhs_T, class Rhs_T>
454
+ concept any_op = is_op<Lhs_T> or is_op<Rhs_T>;
566
455
 
567
456
  /**
568
- * @brief Fallback function template for is_convertible, returns false if
569
- * the conversion is not valid.
457
+ * @brief C++20 concept satisfied when a type can be used as a test
458
+ * expression in `expect()` or `assume()`.
570
459
  *
571
- * @tparam ...Unused Unused template parameters.
572
- *
573
- * @retval false indicating the conversion is not valid.
460
+ * @tparam T The type to be checked.
574
461
  *
575
462
  * @details
576
- * This overload is selected when the primary `is_convertible` template
577
- * cannot be instantiated, providing a `false` result for invalid
578
- * conversions.
463
+ * The `checkable` concept is satisfied when `T` is either a
464
+ * framework operator type (derived from `op`) or is implicitly
465
+ * convertible to `bool`. It is used to constrain the `expect()` and
466
+ * `assume()` function templates, ensuring that only sensible
467
+ * expression types are accepted.
579
468
  */
580
- template <class...>
581
- constexpr auto
582
- is_convertible (...)
583
- {
584
- return false;
585
- }
469
+ template <class T>
470
+ concept checkable = is_op<T> or std::convertible_to<T, bool>;
586
471
 
587
472
  /**
588
- * @brief Variable template to determine if one type is convertible to
589
- * another.
590
- *
591
- * @tparam From The source type to be checked for convertibility.
592
- * @tparam To The target type to which conversion is tested.
473
+ * @brief C++20 concept satisfied when a type can be appended to the
474
+ * deferred reporter's output via `operator<<`.
593
475
  *
594
- * @retval true if `From` is convertible to `To`.
595
- * @retval false otherwise.
476
+ * @tparam T The type to be checked.
596
477
  *
597
478
  * @details
598
- * The `is_convertible_v` variable template evaluates to `true` if the type
599
- * `From` is implicitly convertible to the type `To`, and `false`
600
- * otherwise. This trait is determined at compile time and is used
601
- * throughout the µTest++ framework to enable type-safe conversions and
602
- * requirements checking in template metaprogramming.
479
+ * The `printable` concept is satisfied when `T` is an arithmetic
480
+ * type or is implicitly convertible to `std::string_view`. It
481
+ * constrains the `operator<<` overload of `deferred_reporter_base`,
482
+ * ensuring that only types that can be meaningfully appended to the
483
+ * output message are accepted.
603
484
  */
604
- template <class From, class To>
605
- constexpr auto is_convertible_v = is_convertible<From, To> (0);
606
- #endif
485
+ template <class T>
486
+ concept printable = std::is_arithmetic_v<T>
487
+ or std::is_convertible_v<T, std::string_view>;
488
+
489
+ // ------------------------------------------------------------------------
607
490
 
608
491
  /**
609
- * @brief Struct template for SFINAE requirements.
492
+ * @brief Base struct template providing common storage and accessors
493
+ * for runtime value-wrapper types.
494
+ *
495
+ * @tparam T The type of the stored value.
610
496
  *
611
497
  * @details
612
- * The `requires_` struct template is a utility for SFINAE (Substitution
613
- * Failure Is Not An Error) in template metaprogramming. It is typically
614
- * used to enable or disable template specialisations and function
615
- * templates based on compile-time boolean conditions.
498
+ * The `value_base_` struct template provides the `T value_{}` member,
499
+ * an explicit `operator T()` conversion, and a `get()` accessor,
500
+ * shared by `genuine_integral_value`, `value<T>`, and the floating
501
+ * point specialisation `value<T>`.
616
502
  *
617
- * When the boolean template parameter is `true`, the specialisation
618
- * provides a nested `type` alias, which can be used in conjunction with
619
- * `typename` and `requires_t` to enforce requirements in template
620
- * declarations.
503
+ * It inherits from `op` so that all derived types satisfy the `is_op`
504
+ * concept without each struct needing to inherit from `op` directly.
621
505
  *
622
506
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
623
507
  */
624
- template <bool Cond>
625
- struct requires_
508
+ template <class T>
509
+ struct value_base_ : op
626
510
  {
627
- };
511
+ /**
512
+ * @brief The type of the stored value.
513
+ */
514
+ using value_type = T;
628
515
 
629
- /**
630
- * @brief Specialisation of the requirements struct template for `true`.
631
- *
632
- * @details
633
- * When the condition is `true`, this specialisation provides a nested
634
- * `type` alias, typically used for SFINAE and requirements checking in
635
- * template metaprogramming.
636
- *
637
- * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
638
- */
639
- template <>
640
- struct requires_<true>
641
- {
642
516
  /**
643
- * @brief Alias type provided when the requirement is satisfied.
517
+ * @brief Constructs a `value_base_` with the given value.
518
+ *
519
+ * @param v The value to be stored.
644
520
  */
645
- using type = int;
646
- };
521
+ constexpr explicit value_base_ (const T& v) noexcept;
647
522
 
648
- /**
649
- * @brief Alias template for extracting the `type` member from `requires_`.
650
- *
651
- * @tparam Cond The boolean condition to be checked at compile time.
652
- *
653
- * @details
654
- * The `requires_t` alias template simplifies the use of the `requires_`
655
- * struct template by directly exposing the nested `type` member. It is
656
- * commonly used to enforce compile-time requirements in template
657
- * declarations.
658
- */
659
- template <bool Cond>
660
- using requires_t = typename requires_<Cond>::type;
523
+ /**
524
+ * @brief Explicit conversion operator to the underlying value type.
525
+ *
526
+ * @return The stored value as type `T`.
527
+ */
528
+ [[nodiscard]] constexpr explicit
529
+ operator T () const noexcept;
661
530
 
662
- /**
663
- * @brief Empty base struct for all operator types.
664
- *
665
- * @details
666
- * The `op` struct serves as a common base for all operator and value
667
- * wrapper types used in the µTest++ framework's type traits and
668
- * metaprogramming utilities. It provides a unified type hierarchy,
669
- * enabling compile-time detection and generic handling of operator-like
670
- * types within the framework.
671
- *
672
- * This struct is intended for internal use as a base for integral
673
- * constants, floating point constants, and other value wrappers,
674
- * supporting advanced template metaprogramming and type introspection.
675
- *
676
- * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
677
- */
678
- struct op
679
- {
531
+ /**
532
+ * @brief Getter for the stored value.
533
+ *
534
+ * @par Parameters
535
+ * None.
536
+ * @return The stored value.
537
+ */
538
+ [[nodiscard]] constexpr T
539
+ get (void) const noexcept;
540
+
541
+ /**
542
+ * @brief The stored value.
543
+ */
544
+ T value_{};
680
545
  };
681
546
 
682
547
  /**
@@ -687,75 +552,36 @@ namespace micro_os_plus::micro_test_plus
687
552
  * @details
688
553
  * The `integral_constant` struct template provides a compile-time constant
689
554
  * value of an integral type, with additional utility features. It inherits
690
- * from `op` to enable unified handling within the µTest++ framework's type
691
- * traits and metaprogramming utilities.
555
+ * from `value_base_<decltype(N)>`, which supplies the `value_type` alias,
556
+ * the `value_` runtime member, the explicit conversion operator, and the
557
+ * `get()` accessor.
692
558
  *
693
- * This struct template exposes the constant value via a static member, a
694
- * getter method, and explicit conversion operators. It also provides a
559
+ * This struct retains the compile-time `value` constant and provides a
695
560
  * unary minus operator to obtain the negative value as a new
696
561
  * `integral_constant` instance.
697
562
  *
698
563
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
699
564
  */
700
565
  template <auto N>
701
- struct integral_constant : op
566
+ struct integral_constant : value_base_<decltype (N)>
702
567
  {
703
568
  /**
704
- * @brief The type of the constant value.
569
+ * @brief The compile-time constant value.
705
570
  */
706
- using value_type = decltype (N);
571
+ static constexpr auto value = N;
707
572
 
708
573
  /**
709
- * @brief The constant value.
574
+ * @brief Default constructor. Initialises the base with `N`.
710
575
  */
711
- static constexpr auto value = N;
576
+ constexpr integral_constant () noexcept;
712
577
 
713
578
  /**
714
579
  * @brief Unary minus operator.
715
580
  *
716
581
  * @return An `integral_constant` with value `-N`.
717
- *
718
- * @details
719
- * Returns a new `integral_constant` instance representing the negative
720
- * of the current value.
721
- */
722
- [[nodiscard]] constexpr auto
723
- operator- () const
724
- {
725
- return integral_constant<-N>{};
726
- }
727
-
728
- /**
729
- * @brief Explicit conversion operator to value_type.
730
- *
731
- * @par Parameters
732
- * None.
733
- * @return The constant value as type `value_type`.
734
- *
735
- * @details
736
- * Allows explicit conversion to the underlying value type.
737
- */
738
- [[nodiscard]] constexpr explicit
739
- operator value_type (void) const
740
- {
741
- return N;
742
- }
743
-
744
- /**
745
- * @brief Getter for the constant value.
746
- *
747
- * @par Parameters
748
- * None.
749
- * @return The constant value.
750
- *
751
- * @details
752
- * Returns the compile-time constant value.
753
582
  */
754
583
  [[nodiscard]] constexpr auto
755
- get (void) const
756
- {
757
- return N;
758
- }
584
+ operator- () const noexcept;
759
585
  };
760
586
 
761
587
  /**
@@ -772,23 +598,28 @@ namespace micro_os_plus::micro_test_plus
772
598
  * @details
773
599
  * The `floating_point_constant` struct template provides a compile-time
774
600
  * constant value of a floating point type, supporting custom size and
775
- * precision. It inherits from `op` to enable unified handling within the
776
- * µTest++ framework's type traits and metaprogramming utilities.
777
- *
778
- * This struct template exposes the constant value via a static member, a
779
- * getter method, and explicit conversion operators. It also provides a
780
- * unary minus operator to obtain the negative value as a new
781
- * `floating_point_constant` instance. The `epsilon` member defines the
782
- * precision used for floating point comparisons, calculated based on the
783
- * specified size.
601
+ * precision. It inherits from `op` directly rather than from
602
+ * `value_base_<T>`, which avoids introducing a user-provided constructor
603
+ * into the type and keeps it trivially default-constructible. This
604
+ * prevents the GCC ARM PSABI note about parameter-passing ABI changes
605
+ * that is emitted for non-trivially-constructible types under C++17.
606
+ *
607
+ * The `value_type` alias, explicit conversion operator, and `get()`
608
+ * accessor are provided directly by this struct. The compile-time
609
+ * `epsilon` and `value` static constants are retained, and a unary
610
+ * minus operator is provided to obtain the negative value as a new
611
+ * `floating_point_constant` instance.
784
612
  *
785
613
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
786
614
  */
787
615
  template <class T, auto N, auto D, auto Size, auto P = 1>
788
616
  struct floating_point_constant : op
789
617
  {
618
+ static_assert (P == 1 || P == -1,
619
+ "floating_point_constant: P must be +1 or -1");
620
+
790
621
  /**
791
- * @brief The type of the constant value.
622
+ * @brief The type of the stored value.
792
623
  */
793
624
  using value_type = T;
794
625
 
@@ -801,7 +632,7 @@ namespace micro_os_plus::micro_test_plus
801
632
  static constexpr auto epsilon = T (1) / math::pow (T (10), Size - 1);
802
633
 
803
634
  /**
804
- * @brief The constant value.
635
+ * @brief The compile-time constant value.
805
636
  *
806
637
  * @details
807
638
  * Computed as `P * (N + D / 10^Size)`.
@@ -810,48 +641,30 @@ namespace micro_os_plus::micro_test_plus
810
641
  = T (P) * (T (N) + (T (D) / math::pow (T (10), Size)));
811
642
 
812
643
  /**
813
- * @brief Unary minus operator.
814
- *
815
- * @return A `floating_point_constant` with value `-value`.
644
+ * @brief Explicit conversion operator to the underlying value type.
816
645
  *
817
- * @details
818
- * Returns a new `floating_point_constant` instance representing the
819
- * negative of the current value.
646
+ * @return The compile-time constant as type `T`.
820
647
  */
821
- [[nodiscard]] constexpr auto
822
- operator- () const
823
- {
824
- return floating_point_constant<T, N, D, Size, -1>{};
825
- }
648
+ [[nodiscard]] constexpr explicit
649
+ operator T () const noexcept;
826
650
 
827
651
  /**
828
- * @brief Explicit conversion operator to value_type.
652
+ * @brief Getter for the compile-time constant value.
829
653
  *
830
- * @return The constant value as type `value_type`.
831
- *
832
- * @details
833
- * Allows explicit conversion to the underlying floating point value
834
- * type.
654
+ * @par Parameters
655
+ * None.
656
+ * @return The compile-time constant as type `T`.
835
657
  */
836
- [[nodiscard]] constexpr explicit
837
- operator value_type () const
838
- {
839
- return value;
840
- }
658
+ [[nodiscard]] constexpr T
659
+ get (void) const noexcept;
841
660
 
842
661
  /**
843
- * @brief Getter for the constant value.
844
- *
845
- * @return The constant value.
662
+ * @brief Unary minus operator.
846
663
  *
847
- * @details
848
- * Returns the compile-time floating point constant value.
664
+ * @return A `floating_point_constant` with negated sign parameter.
849
665
  */
850
666
  [[nodiscard]] constexpr auto
851
- get () const
852
- {
853
- return value;
854
- }
667
+ operator- () const noexcept;
855
668
  };
856
669
 
857
670
  /**
@@ -861,161 +674,44 @@ namespace micro_os_plus::micro_test_plus
861
674
  *
862
675
  * @details
863
676
  * The `genuine_integral_value` struct template encapsulates a runtime
864
- * integral value, providing a consistent interface for value access and
865
- * conversion. It inherits from `op` to enable unified handling within the
866
- * µTest++ framework's type traits and metaprogramming utilities.
867
- *
868
- * This struct template exposes the value via a member variable, a getter
869
- * method, and an explicit conversion operator. It is intended for use
870
- * cases where a value must be wrapped and treated generically within the
871
- * framework, supporting advanced template metaprogramming and type
872
- * introspection.
677
+ * integral value. The stored value, explicit conversion operator, and
678
+ * getter are provided by the `value_base_` base.
873
679
  *
874
680
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
875
681
  */
876
682
  template <class T>
877
- struct genuine_integral_value : op
683
+ struct genuine_integral_value : value_base_<T>
878
684
  {
879
- /**
880
- * @brief The type of the encapsulated value.
881
- */
882
- using value_type = T;
883
-
884
685
  /**
885
686
  * @brief Constructs a genuine_integral_value with the specified value.
886
687
  *
887
688
  * @param _value The integral value to be stored.
888
689
  */
889
- constexpr genuine_integral_value (const T& _value) : value_{ _value }
890
- {
891
- }
892
-
893
- /**
894
- * @brief Explicit conversion operator to the underlying value type.
895
- *
896
- * @return The stored value as type `T`.
897
- *
898
- * @details
899
- * Allows explicit conversion to the encapsulated value.
900
- */
901
- [[nodiscard]] constexpr explicit
902
- operator T () const
903
- {
904
- return value_;
905
- }
906
-
907
- /**
908
- * @brief Getter for the encapsulated value.
909
- *
910
- * @return The value of type `T`.
911
- *
912
- * @details
913
- * Returns the stored integral value.
914
- */
915
- [[nodiscard]] constexpr decltype (auto)
916
- get () const
917
- {
918
- return value_;
919
- }
920
-
921
- /**
922
- * @brief The encapsulated integral value.
923
- */
924
- T value_{};
690
+ constexpr genuine_integral_value (const T& _value) noexcept;
925
691
  };
926
692
 
927
- /**
928
- * @brief Variable template to determine if a type derives from `op`.
929
- *
930
- * @tparam T The type to be checked for derivation from `op`.
931
- *
932
- * @retval true if `T` is derived from `type_traits::op`.
933
- * @retval false otherwise.
934
- *
935
- * @details
936
- * The `is_op_v` variable template evaluates to `true` if the given type
937
- * `T` is derived from the `type_traits::op` base struct, and `false`
938
- * otherwise. This trait is determined at compile time using compiler
939
- * intrinsics and is used throughout the µTest++ framework to enable
940
- * generic handling and detection of operator-like or value wrapper types
941
- * in template metaprogramming.
942
- */
943
- template <class T>
944
- inline constexpr auto is_op_v = __is_base_of (type_traits::op, T);
945
-
946
693
  /**
947
694
  * @brief Struct template representing a generic value, accessible via a
948
695
  * getter.
949
696
  *
950
697
  * @tparam T The type of the value to be encapsulated.
951
- * @tparam Opt An optional parameter for SFINAE or specialisation,
952
- * defaults to `int`.
953
698
  *
954
699
  * @details
955
- * The `value` struct template encapsulates a value of type `T`, providing
956
- * a consistent interface for value access and conversion. It inherits from
957
- * `type_traits::op` to enable unified handling within the µTest++
958
- * framework's type traits and metaprogramming utilities.
959
- *
960
- * This struct template exposes the value via a member variable, a getter
961
- * method, and an explicit conversion operator. It is intended for use
962
- * cases where a value must be wrapped and treated generically within the
963
- * framework, supporting advanced template metaprogramming and type
964
- * introspection.
700
+ * The `value` struct template encapsulates a value of type `T`. The
701
+ * stored value, explicit conversion operator, and getter are provided
702
+ * by the `value_base_` base.
965
703
  *
966
704
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
967
705
  */
968
- template <class T, class Opt = int>
969
- struct value : type_traits::op
706
+ template <class T>
707
+ struct value : value_base_<T>
970
708
  {
971
- /**
972
- * @brief The type of the encapsulated value.
973
- */
974
- using value_type = T;
975
-
976
709
  /**
977
710
  * @brief Constructs a value object with the specified value.
978
711
  *
979
712
  * @param _value The value to be stored.
980
713
  */
981
- constexpr value (const T& _value) : value_{ _value }
982
- {
983
- }
984
-
985
- /**
986
- * @brief Explicit conversion operator to the underlying value type.
987
- *
988
- * @return The stored value as type `T`.
989
- *
990
- * @details
991
- * Allows explicit conversion to the encapsulated value.
992
- */
993
- [[nodiscard]] constexpr explicit
994
- operator T () const
995
- {
996
- return value_;
997
- }
998
-
999
- /**
1000
- * @brief Getter for the encapsulated value.
1001
- *
1002
- * @par Parameters
1003
- * None.
1004
- * @return The value of type `T`.
1005
- *
1006
- * @details
1007
- * Returns the stored value.
1008
- */
1009
- [[nodiscard]] constexpr decltype (auto)
1010
- get (void) const
1011
- {
1012
- return value_;
1013
- }
1014
-
1015
- /**
1016
- * @brief The encapsulated value.
1017
- */
1018
- T value_{};
714
+ constexpr value (const T& _value) noexcept;
1019
715
  };
1020
716
 
1021
717
  /**
@@ -1027,15 +723,12 @@ namespace micro_os_plus::micro_test_plus
1027
723
  * @details
1028
724
  * The `value` struct template specialisation for floating point types
1029
725
  * encapsulates a value of type `T` and provides an associated `epsilon`
1030
- * for precision control during comparisons. It inherits from
1031
- * `type_traits::op` to enable unified handling within the µTest++
1032
- * framework's type traits and metaprogramming utilities.
726
+ * for precision control during comparisons. The stored value, explicit
727
+ * conversion operator, and getter are provided by the `value_base_` base.
1033
728
  *
1034
- * This struct template exposes the value via a member variable, a getter
1035
- * method, and an explicit conversion operator. The `epsilon` member
1036
- * defines the precision used for floating point comparisons and can be set
1037
- * explicitly or computed as a default based on the number of decimal
1038
- * digits in the value.
729
+ * The `epsilon` member defines the precision used for floating point
730
+ * comparisons and can be set explicitly or computed as a default based
731
+ * on the number of decimal digits in the value.
1039
732
  *
1040
733
  * This specialisation is intended for use cases where floating point
1041
734
  * values require controlled precision, supporting advanced template
@@ -1044,87 +737,35 @@ namespace micro_os_plus::micro_test_plus
1044
737
  * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
1045
738
  */
1046
739
  template <class T>
1047
- struct value<T,
1048
- type_traits::requires_t<type_traits::is_floating_point_v<T>>>
1049
- : type_traits::op
740
+ requires is_floating_point<T>
741
+ struct value<T> : value_base_<T>
1050
742
  {
1051
743
  /**
1052
- * @brief The type of the encapsulated value.
1053
- */
1054
- using value_type = T;
1055
-
1056
- /**
1057
- * @brief The epsilon value used for floating point comparisons.
744
+ * @brief The epsilon value used for floating-point comparisons.
1058
745
  *
1059
746
  * @details
1060
- * This static inline member defines the precision for comparisons. It
1061
- * can be set explicitly via the constructor or computed as a default
1062
- * based on the number of decimal digits in the value.
747
+ * This instance member defines the precision for comparisons. It
748
+ * is set via the constructor, either explicitly or computed as a
749
+ * default based on the number of decimal digits in the value.
750
+ * Each instance carries its own epsilon, so two `value<T>` objects
751
+ * with different precisions do not interfere with each other.
1063
752
  */
1064
- static inline auto epsilon = T{}; // Why static?
753
+ T epsilon = T{};
1065
754
 
1066
755
  /**
1067
- * @brief Constructs a floating point value with a specified precision.
756
+ * @brief Constructs a floating-point value with a specified precision.
1068
757
  *
1069
- * @param _value The floating point value to be stored.
758
+ * @param _value The floating-point value to be stored.
1070
759
  * @param precision The epsilon value to be used for comparisons.
1071
760
  */
1072
- constexpr value (const T& _value, const T precision) : value_{ _value }
1073
- {
1074
- epsilon = precision;
1075
- }
761
+ constexpr value (const T& _value, const T precision) noexcept;
1076
762
 
1077
763
  /**
1078
764
  * @brief Constructs a floating point value with default precision.
1079
765
  *
1080
766
  * @param val The floating point value to be stored.
1081
- *
1082
- * @details
1083
- * The epsilon is computed as 1 divided by 10 raised to the number of
1084
- * decimal digits in the value.
1085
- */
1086
- constexpr /*explicit(false)*/ value (const T& val)
1087
- : value{ val,
1088
- T (1)
1089
- / math::pow (T (10),
1090
- math::den_size<unsigned long long> (val)) }
1091
- {
1092
- }
1093
-
1094
- /**
1095
- * @brief Explicit conversion operator to the underlying value type.
1096
- *
1097
- * @return The stored value as type `T`.
1098
- *
1099
- * @details
1100
- * Allows explicit conversion to the encapsulated floating point value.
1101
767
  */
1102
- [[nodiscard]] constexpr explicit
1103
- operator T () const
1104
- {
1105
- return value_;
1106
- }
1107
-
1108
- /**
1109
- * @brief Getter for the encapsulated value.
1110
- *
1111
- * @par Parameters
1112
- * None.
1113
- * @return The value of type `T`.
1114
- *
1115
- * @details
1116
- * Returns the stored floating point value.
1117
- */
1118
- [[nodiscard]] constexpr decltype (auto)
1119
- get (void) const
1120
- {
1121
- return value_;
1122
- }
1123
-
1124
- /**
1125
- * @brief The encapsulated floating point value.
1126
- */
1127
- T value_{};
768
+ constexpr value (const T& val);
1128
769
  };
1129
770
 
1130
771
  // ------------------------------------------------------------------------
@@ -1141,6 +782,11 @@ namespace micro_os_plus::micro_test_plus
1141
782
 
1142
783
  #endif // __cplusplus
1143
784
 
785
+ // ============================================================================
786
+ // Templates & constexpr implementations.
787
+
788
+ #include "inlines/type-traits-inlines.h"
789
+
1144
790
  // ----------------------------------------------------------------------------
1145
791
 
1146
792
  #endif // MICRO_TEST_PLUS_TYPE_TRAITS_H_