@micro-os-plus/micro-test-plus 4.0.0 → 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 (51) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/CMakeLists.txt +74 -24
  3. package/README.md +3 -2
  4. package/include/micro-os-plus/micro-test-plus/README.md +6 -0
  5. package/include/micro-os-plus/micro-test-plus/deferred-reporter.h +29 -54
  6. package/include/micro-os-plus/micro-test-plus/detail.h +166 -705
  7. package/include/micro-os-plus/micro-test-plus/exceptions.h +5 -6
  8. package/include/micro-os-plus/micro-test-plus/expression-formatter.h +669 -0
  9. package/include/micro-os-plus/micro-test-plus/function-comparators.h +5 -0
  10. package/include/micro-os-plus/micro-test-plus/inlines/deferred-reporter-inlines.h +25 -30
  11. package/include/micro-os-plus/micro-test-plus/inlines/detail-inlines.h +711 -0
  12. package/include/micro-os-plus/micro-test-plus/inlines/exceptions-inline.h +137 -0
  13. package/include/micro-os-plus/micro-test-plus/inlines/expression-formatter-inlines.h +510 -0
  14. package/include/micro-os-plus/micro-test-plus/inlines/function-comparators-inlines.h +17 -76
  15. package/include/micro-os-plus/micro-test-plus/inlines/literals-inlines.h +47 -25
  16. package/include/micro-os-plus/micro-test-plus/inlines/math-inlines.h +7 -7
  17. package/include/micro-os-plus/micro-test-plus/inlines/operators-inlines.h +275 -0
  18. package/include/micro-os-plus/micro-test-plus/inlines/reflection-inlines.h +4 -4
  19. package/include/micro-os-plus/micro-test-plus/inlines/reporter-inlines.h +53 -394
  20. package/include/micro-os-plus/micro-test-plus/inlines/runner-inlines.h +38 -0
  21. package/include/micro-os-plus/micro-test-plus/inlines/runner-totals-inlines.h +152 -0
  22. package/include/micro-os-plus/micro-test-plus/inlines/test-inlines.h +231 -45
  23. package/include/micro-os-plus/micro-test-plus/inlines/timings-inlines.h +120 -0
  24. package/include/micro-os-plus/micro-test-plus/inlines/type-traits-inlines.h +231 -0
  25. package/include/micro-os-plus/micro-test-plus/literals.h +8 -14
  26. package/include/micro-os-plus/micro-test-plus/math.h +5 -0
  27. package/include/micro-os-plus/micro-test-plus/operators.h +19 -169
  28. package/include/micro-os-plus/micro-test-plus/reflection.h +5 -12
  29. package/include/micro-os-plus/micro-test-plus/reporter-human.h +17 -11
  30. package/include/micro-os-plus/micro-test-plus/reporter-tap.h +14 -8
  31. package/include/micro-os-plus/micro-test-plus/reporter.h +101 -424
  32. package/include/micro-os-plus/micro-test-plus/runner-totals.h +162 -176
  33. package/include/micro-os-plus/micro-test-plus/runner.h +61 -42
  34. package/include/micro-os-plus/micro-test-plus/test.h +450 -506
  35. package/include/micro-os-plus/micro-test-plus/timings.h +259 -262
  36. package/include/micro-os-plus/micro-test-plus/type-traits.h +19 -67
  37. package/include/micro-os-plus/micro-test-plus/utility.h +5 -4
  38. package/include/micro-os-plus/micro-test-plus.h +33 -24
  39. package/meson.build +1 -0
  40. package/package.json +11 -3
  41. package/src/deferred-reporter.cpp +21 -2
  42. package/src/expression-formatter.cpp +289 -0
  43. package/src/reflection.cpp +3 -1
  44. package/src/reporter-human.cpp +31 -37
  45. package/src/reporter-tap.cpp +25 -35
  46. package/src/reporter.cpp +36 -231
  47. package/src/runner-totals.cpp +6 -3
  48. package/src/runner.cpp +131 -25
  49. package/src/test.cpp +120 -113
  50. package/src/timings.cpp +6 -5
  51. package/src/utility.cpp +1 -1
@@ -55,6 +55,13 @@
55
55
  #include <cstdio>
56
56
  #include <cstring>
57
57
 
58
+ #if defined(MICRO_OS_PLUS_TRACE)
59
+ #include <micro-os-plus/diag/trace.h>
60
+ #endif // MICRO_OS_PLUS_TRACE
61
+
62
+ #include "micro-os-plus/micro-test-plus/deferred-reporter.h"
63
+ #include "micro-os-plus/micro-test-plus/reporter.h"
64
+
58
65
  // ----------------------------------------------------------------------------
59
66
 
60
67
  #if defined(__GNUC__)
@@ -64,6 +71,7 @@
64
71
  #pragma clang diagnostic ignored "-Wc++98-compat"
65
72
  #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
66
73
  #else // GCC only
74
+ #pragma GCC diagnostic ignored "-Wredundant-tags"
67
75
  #endif
68
76
  #endif
69
77
 
@@ -71,36 +79,135 @@
71
79
 
72
80
  namespace micro_os_plus::micro_test_plus
73
81
  {
74
- // ==========================================================================
75
-
76
- /**
77
- * @details
78
- * Binds the callable and its arguments into the stored `callable_` function
79
- * object. When `run()` is called, the stored function is invoked with a
80
- * reference to the derived `Self_T` instance as its first argument,
81
- * followed by the bound arguments.
82
- */
83
- template <typename Self_T>
84
- template <typename Callable_T, typename... Args_T>
85
- runnable<Self_T>::runnable (const char* name, class runner& runner,
86
- size_t own_index, Callable_T&& callable,
87
- Args_T&&... arguments)
88
- : runnable_base{ name, runner, own_index }
82
+ namespace detail
89
83
  {
90
- // When there are no extra arguments the callable already has the signature
91
- // void(Self_T&), so store it directly. Only use std::bind when additional
92
- // arguments must be pre-bound, to avoid triggering a GCC ARM bug in
93
- // __is_nothrow_invocable<_Bind<...>, Self_T&> (GCC 15.2.1).
94
- if constexpr (sizeof...(arguments) == 0)
95
- {
96
- callable_ = std::forward<Callable_T> (callable);
97
- }
98
- else
99
- {
100
- callable_ = std::bind (std::forward<Callable_T> (callable),
101
- std::placeholders::_1,
102
- std::forward<Args_T> (arguments)...);
103
- }
84
+ // ========================================================================
85
+
86
+ /**
87
+ * @details
88
+ * Returns a pointer to the null-terminated name stored in `name_`.
89
+ */
90
+ inline const char*
91
+ test_node::name (void) const noexcept
92
+ {
93
+ return name_;
94
+ }
95
+
96
+ /**
97
+ * @details
98
+ * Returns a reference to the `runner_totals` member.
99
+ */
100
+ inline runner_totals&
101
+ test_node::totals () noexcept
102
+ {
103
+ return totals_;
104
+ }
105
+
106
+ /**
107
+ * @details
108
+ * Returns a const reference to the `runner_totals` member.
109
+ */
110
+ inline const runner_totals&
111
+ test_node::totals () const noexcept
112
+ {
113
+ return totals_;
114
+ }
115
+
116
+ // ========================================================================
117
+
118
+ /**
119
+ * @details
120
+ * Returns the one-based positional index of this object within its parent.
121
+ */
122
+ inline size_t
123
+ runnable_base::own_index () const noexcept
124
+ {
125
+ return own_index_;
126
+ }
127
+
128
+ /**
129
+ * @details
130
+ * Sets the positional index of this object within its parent.
131
+ */
132
+ inline void
133
+ runnable_base::own_index (size_t index) noexcept
134
+ {
135
+ own_index_ = index;
136
+ }
137
+
138
+ /**
139
+ * @details
140
+ * Returns the sequential index of the most recently created child subtest.
141
+ */
142
+ inline size_t
143
+ runnable_base::current_subtest_index () const noexcept
144
+ {
145
+ return current_subtest_index_;
146
+ }
147
+
148
+ /**
149
+ * @details
150
+ * Each call to `test()` invokes this method before constructing the new
151
+ * `subtest`, so the index values form a strictly increasing, one-based
152
+ * sequence.
153
+ */
154
+ inline size_t
155
+ runnable_base::increment_subtest_index () noexcept
156
+ {
157
+ return ++current_subtest_index_;
158
+ }
159
+
160
+ /**
161
+ * @details
162
+ * Returns the number of child subtests owned by this node.
163
+ */
164
+ inline size_t
165
+ runnable_base::children_subtests_count (void) const noexcept
166
+ {
167
+ return children_subtests_.size ();
168
+ }
169
+
170
+ /**
171
+ * @details
172
+ * Returns a reference to the owning test runner.
173
+ */
174
+ inline class runner&
175
+ runnable_base::runner (void) const noexcept
176
+ {
177
+ return runner_;
178
+ }
179
+
180
+ // ========================================================================
181
+
182
+ /**
183
+ * @details
184
+ * Binds the callable and its arguments into the stored `callable_`
185
+ * function object. When `run()` is called, the stored function is invoked
186
+ * with a reference to the derived `Self_T` instance as its first argument,
187
+ * followed by the bound arguments.
188
+ */
189
+ template <typename Self_T>
190
+ template <typename Callable_T, typename... Args_T>
191
+ runnable<Self_T>::runnable (const char* name, class runner& runner,
192
+ size_t own_index, Callable_T&& callable,
193
+ Args_T&&... arguments)
194
+ : runnable_base{ name, runner, own_index }
195
+ {
196
+ // When there are no extra arguments the callable already has the
197
+ // signature void(Self_T&), so store it directly. Only use std::bind when
198
+ // additional arguments must be pre-bound, to avoid triggering a GCC ARM
199
+ // bug in
200
+ // __is_nothrow_invocable<_Bind<...>, Self_T&> (GCC 15.2.1).
201
+ if constexpr (sizeof...(arguments) == 0)
202
+ {
203
+ callable_ = std::forward<Callable_T> (callable);
204
+ }
205
+ else
206
+ {
207
+ callable_ = std::bind (std::forward<Callable_T> (callable),
208
+ std::placeholders::_1,
209
+ std::forward<Args_T> (arguments)...);
210
+ }
104
211
 
105
212
  #if defined(MICRO_OS_PLUS_TRACE) \
106
213
  && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
@@ -110,22 +217,22 @@ namespace micro_os_plus::micro_test_plus
110
217
  #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
111
218
  #endif
112
219
  #endif
113
- trace::printf ("%s '%s' %zu\n", __PRETTY_FUNCTION__, name, own_index_);
220
+ trace::printf ("%s '%s' %zu\n", __PRETTY_FUNCTION__, name, own_index_);
114
221
  #if defined(__GNUC__)
115
222
  #pragma GCC diagnostic pop
116
223
  #endif
117
224
  #endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
118
- }
119
-
120
- /**
121
- * @details
122
- * No-op in production builds. When tracing is enabled via
123
- * `MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS`, emits a trace
124
- * message identifying the instance being destroyed.
125
- */
126
- template <typename Self_T>
127
- runnable<Self_T>::~runnable ()
128
- {
225
+ }
226
+
227
+ /**
228
+ * @details
229
+ * No-op in production builds. When tracing is enabled via
230
+ * `MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS`, emits a trace
231
+ * message identifying the instance being destroyed.
232
+ */
233
+ template <typename Self_T>
234
+ runnable<Self_T>::~runnable ()
235
+ {
129
236
  #if defined(MICRO_OS_PLUS_TRACE) \
130
237
  && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
131
238
  #if defined(__GNUC__)
@@ -134,12 +241,15 @@ namespace micro_os_plus::micro_test_plus
134
241
  #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
135
242
  #endif
136
243
  #endif
137
- trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
244
+ trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
138
245
  #if defined(__GNUC__)
139
246
  #pragma GCC diagnostic pop
140
247
  #endif
141
248
  #endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
142
- }
249
+ }
250
+
251
+ // ------------------------------------------------------------------------
252
+ } // namespace detail
143
253
 
144
254
  // ==========================================================================
145
255
 
@@ -208,6 +318,47 @@ namespace micro_os_plus::micro_test_plus
208
318
  after_subtest_create_ (std::move (child_subtest), parent_suite_);
209
319
  }
210
320
 
321
+ /**
322
+ * @details
323
+ * Constructs and returns a `deferred_reporter<Expr_T>` with `abort = false`.
324
+ * The reporter evaluates the condition and records a pass or fail when
325
+ * it is destroyed at the end of the expression statement.
326
+ */
327
+ template <class Expr_T>
328
+ requires type_traits::checkable<Expr_T>
329
+ auto
330
+ subtest::expect (const Expr_T& expr, const reflection::source_location& sl)
331
+ {
332
+ return detail::deferred_reporter{ expr, false, sl, *this,
333
+ reporter ().expression () };
334
+ }
335
+
336
+ /**
337
+ * @details
338
+ * Constructs and returns a `deferred_reporter<Expr_T>` with `abort = true`.
339
+ * The reporter evaluates the condition, records a pass or fail when it is
340
+ * destroyed, and aborts execution if the condition is false.
341
+ */
342
+ template <class Expr_T>
343
+ requires type_traits::checkable<Expr_T>
344
+ auto
345
+ subtest::assume (const Expr_T& expr, const reflection::source_location& sl)
346
+ {
347
+ return detail::deferred_reporter{ expr, true, sl, *this,
348
+ reporter ().expression () };
349
+ }
350
+
351
+ /**
352
+ * @details
353
+ * Top-level subtests (direct children of a `suite`) have depth 1.
354
+ * Each additional level of nesting increments the depth by 1.
355
+ */
356
+ inline size_t
357
+ subtest::nesting_depth () const noexcept
358
+ {
359
+ return nesting_depth_;
360
+ }
361
+
211
362
  // ==========================================================================
212
363
 
213
364
  /**
@@ -308,6 +459,41 @@ namespace micro_os_plus::micro_test_plus
308
459
  after_subtest_create_ (std::move (child_subtest), *this);
309
460
  }
310
461
 
462
+ /**
463
+ * @details
464
+ * Returns a reference to the `timestamps` member.
465
+ */
466
+ inline detail::timestamps&
467
+ suite::timings () noexcept
468
+ {
469
+ return timings_;
470
+ }
471
+
472
+ /**
473
+ * @details
474
+ * Returns a const reference to the `timestamps` member.
475
+ */
476
+ inline const detail::timestamps&
477
+ suite::timings () const noexcept
478
+ {
479
+ return timings_;
480
+ }
481
+
482
+ // ==========================================================================
483
+
484
+ /**
485
+ * @details
486
+ * Sets the name of the top-level suite.
487
+ *
488
+ * Used internally by the runner to set the name of the top suite after
489
+ * initialisation.
490
+ */
491
+ inline void
492
+ top_suite::name (const char* new_name) noexcept
493
+ {
494
+ name_ = new_name;
495
+ }
496
+
311
497
  // ==========================================================================
312
498
 
313
499
  /**
@@ -321,7 +507,7 @@ namespace micro_os_plus::micro_test_plus
321
507
  Callable_T&& callable, Args_T&&... arguments)
322
508
  // The nullptr passed to the base constructor is an optimisation to save
323
509
  // some space, since this callble is not used by the static runner.
324
- : suite{ name, runner, nullptr }
510
+ : suite{ name, detail::to_runner (runner), nullptr }
325
511
  {
326
512
  if constexpr (sizeof...(arguments) == 0)
327
513
  {
@@ -348,7 +534,7 @@ namespace micro_os_plus::micro_test_plus
348
534
  #endif
349
535
  #endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
350
536
 
351
- static_runner::register_static_suite (runner, *this);
537
+ detail::register_static_suite (runner, *this);
352
538
  }
353
539
 
354
540
  // --------------------------------------------------------------------------
@@ -0,0 +1,120 @@
1
+ /*
2
+ * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3
+ * Copyright (c) 2021-2026 Liviu Ionescu. All rights reserved.
4
+ *
5
+ * Permission to use, copy, modify, and/or distribute this software for any
6
+ * purpose is hereby granted, under the terms of the MIT license.
7
+ *
8
+ * If a copy of the license was not distributed with this file, it can be
9
+ * obtained from https://opensource.org/licenses/mit.
10
+ */
11
+
12
+ // ----------------------------------------------------------------------------
13
+
14
+ /**
15
+ * @file
16
+ * @brief C++ header file with inline implementations for the µTest++
17
+ * timing utilities.
18
+ *
19
+ * @details
20
+ * This header provides the inline method bodies for the `timestamp` and
21
+ * `timestamps` classes, separated from the class declarations in
22
+ * `timings.h` to enforce the project convention that declarations reside
23
+ * in headers and implementations reside in inline files.
24
+ *
25
+ * All definitions reside within the `micro_os_plus::micro_test_plus`
26
+ * namespace, ensuring clear separation from user code and minimising
27
+ * the risk of naming conflicts.
28
+ */
29
+
30
+ #ifndef MICRO_TEST_PLUS_TIMINGS_INLINES_H_
31
+ #define MICRO_TEST_PLUS_TIMINGS_INLINES_H_
32
+
33
+ // ----------------------------------------------------------------------------
34
+
35
+ #ifdef __cplusplus
36
+
37
+ // ----------------------------------------------------------------------------
38
+
39
+ #if defined(__GNUC__)
40
+ #pragma GCC diagnostic push
41
+ #if defined(__clang__)
42
+ #pragma clang diagnostic ignored "-Wc++98-compat"
43
+ #pragma clang diagnostic ignored "-Wpre-c++17-compat"
44
+ #endif
45
+ #endif
46
+
47
+ // ============================================================================
48
+
49
+ namespace micro_os_plus::micro_test_plus::detail
50
+ {
51
+ // ==========================================================================
52
+
53
+ /**
54
+ * @details
55
+ * Stores the supplied `timespec` value in the `value_` member.
56
+ */
57
+ inline timestamp::timestamp (const timespec& ts) noexcept : value_{ ts }
58
+ {
59
+ }
60
+
61
+ /**
62
+ * @details
63
+ * Returns a mutable reference to the `value_` member.
64
+ */
65
+ inline timespec&
66
+ timestamp::value () noexcept
67
+ {
68
+ return value_;
69
+ }
70
+
71
+ /**
72
+ * @details
73
+ * Returns a const reference to the `value_` member.
74
+ */
75
+ inline const timespec&
76
+ timestamp::value () const noexcept
77
+ {
78
+ return value_;
79
+ }
80
+
81
+ // ==========================================================================
82
+
83
+ /**
84
+ * @details
85
+ * Returns `true` when `begin_time_` holds a value, i.e. when
86
+ * `timestamp_begin()` has previously been called.
87
+ */
88
+ inline bool
89
+ timestamps::has_begin () const noexcept
90
+ {
91
+ return begin_time_.has_value ();
92
+ }
93
+
94
+ /**
95
+ * @details
96
+ * Returns `true` when `end_time_` holds a value, i.e. when
97
+ * `timestamp_end()` has previously been called.
98
+ */
99
+ inline bool
100
+ timestamps::has_end () const noexcept
101
+ {
102
+ return end_time_.has_value ();
103
+ }
104
+
105
+ // --------------------------------------------------------------------------
106
+ } // namespace micro_os_plus::micro_test_plus::detail
107
+
108
+ #if defined(__GNUC__)
109
+ #pragma GCC diagnostic pop
110
+ #endif
111
+
112
+ // ----------------------------------------------------------------------------
113
+
114
+ #endif // __cplusplus
115
+
116
+ // ----------------------------------------------------------------------------
117
+
118
+ #endif // MICRO_TEST_PLUS_TIMINGS_INLINES_H_
119
+
120
+ // ----------------------------------------------------------------------------
@@ -0,0 +1,231 @@
1
+ /*
2
+ * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3
+ * Copyright (c) 2021-2026 Liviu Ionescu. All rights reserved.
4
+ *
5
+ * Permission to use, copy, modify, and/or distribute this software for any
6
+ * purpose is hereby granted, under the terms of the MIT license.
7
+ *
8
+ * If a copy of the license was not distributed with this file, it can be
9
+ * obtained from https://opensource.org/licenses/mit.
10
+ *
11
+ * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
12
+ * released under the terms of the Boost Version 1.0 Software License,
13
+ * which can be obtained from https://www.boost.org/LICENSE_1_0.txt.
14
+ */
15
+
16
+ // ----------------------------------------------------------------------------
17
+
18
+ /**
19
+ * @file
20
+ * @brief C++ header file with inline implementations for the µTest++
21
+ * type trait utilities.
22
+ *
23
+ * @details
24
+ * This header provides the out-of-class template and inline implementations
25
+ * for all methods declared in the type-traits struct templates in
26
+ * `type-traits.h`. It defines the bodies of the constructors, conversion
27
+ * operators, and accessor methods for `value_base_`, `integral_constant`,
28
+ * `floating_point_constant`, `genuine_integral_value`, and the `value<T>`
29
+ * templates.
30
+ *
31
+ * Separating the implementations from the declarations keeps `type-traits.h`
32
+ * concise and focused on the interface, whilst grouping all method bodies
33
+ * here for maintainability.
34
+ *
35
+ * All definitions reside within the
36
+ * `micro_os_plus::micro_test_plus::type_traits` namespace, ensuring clear
37
+ * separation from user code and minimising the risk of naming conflicts.
38
+ *
39
+ * This file is intended solely for internal use within the framework and
40
+ * should not be included directly by user code.
41
+ */
42
+
43
+ #ifndef MICRO_TEST_PLUS_TYPE_TRAITS_INLINES_H_
44
+ #define MICRO_TEST_PLUS_TYPE_TRAITS_INLINES_H_
45
+
46
+ // ----------------------------------------------------------------------------
47
+
48
+ #ifdef __cplusplus
49
+
50
+ // ----------------------------------------------------------------------------
51
+
52
+ #if defined(__GNUC__)
53
+ #pragma GCC diagnostic push
54
+ #if defined(__clang__)
55
+ #pragma clang diagnostic ignored "-Wc++98-compat"
56
+ #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
57
+ #endif
58
+ #endif
59
+
60
+ // ============================================================================
61
+
62
+ namespace micro_os_plus::micro_test_plus
63
+ {
64
+ namespace type_traits
65
+ {
66
+ // ========================================================================
67
+
68
+ /**
69
+ * @details
70
+ * Stores the supplied value in the `value_` member.
71
+ */
72
+ template <class T>
73
+ constexpr value_base_<T>::value_base_ (const T& v) noexcept : value_{ v }
74
+ {
75
+ }
76
+
77
+ /**
78
+ * @details
79
+ * Allows explicit conversion to the encapsulated value.
80
+ */
81
+ template <class T>
82
+ constexpr value_base_<T>::
83
+ operator T () const noexcept
84
+ {
85
+ return value_;
86
+ }
87
+
88
+ /**
89
+ * @details
90
+ * Returns the stored value by value.
91
+ */
92
+ template <class T>
93
+ constexpr T
94
+ value_base_<T>::get (void) const noexcept
95
+ {
96
+ return value_;
97
+ }
98
+
99
+ // ------------------------------------------------------------------------
100
+
101
+ /**
102
+ * @details
103
+ * Delegates to `value_base_<decltype(N)>{ N }` to initialise the base.
104
+ */
105
+ template <auto N>
106
+ constexpr integral_constant<N>::integral_constant () noexcept
107
+ : value_base_<decltype (N)>{ N }
108
+ {
109
+ }
110
+
111
+ /**
112
+ * @details
113
+ * Returns a new `integral_constant` instance representing the negative
114
+ * of the current value.
115
+ */
116
+ template <auto N>
117
+ constexpr auto
118
+ integral_constant<N>::operator- () const noexcept
119
+ {
120
+ return integral_constant<-N>{};
121
+ }
122
+
123
+ // ------------------------------------------------------------------------
124
+
125
+ /**
126
+ * @details
127
+ * Returns the compile-time constant value as type `T`.
128
+ */
129
+ template <class T, auto N, auto D, auto Size, auto P>
130
+ constexpr floating_point_constant<T, N, D, Size, P>::
131
+ operator T () const noexcept
132
+ {
133
+ return value;
134
+ }
135
+
136
+ /**
137
+ * @details
138
+ * Returns the compile-time constant value as type `T`.
139
+ */
140
+ template <class T, auto N, auto D, auto Size, auto P>
141
+ constexpr T
142
+ floating_point_constant<T, N, D, Size, P>::get (void) const noexcept
143
+ {
144
+ return value;
145
+ }
146
+
147
+ /**
148
+ * @details
149
+ * Returns a new `floating_point_constant` instance representing the
150
+ * negative of the current value by flipping the sign parameter `P`.
151
+ */
152
+ template <class T, auto N, auto D, auto Size, auto P>
153
+ constexpr auto
154
+ floating_point_constant<T, N, D, Size, P>::operator- () const noexcept
155
+ {
156
+ return floating_point_constant<T, N, D, Size, -P>{};
157
+ }
158
+
159
+ // ------------------------------------------------------------------------
160
+
161
+ /**
162
+ * @details
163
+ * Delegates to `value_base_<T>{ _value }` to initialise the base.
164
+ */
165
+ template <class T>
166
+ constexpr genuine_integral_value<T>::genuine_integral_value (
167
+ const T& _value) noexcept
168
+ : value_base_<T>{ _value }
169
+ {
170
+ }
171
+
172
+ // ------------------------------------------------------------------------
173
+
174
+ /**
175
+ * @details
176
+ * Delegates to `value_base_<T>{ _value }` to initialise the base.
177
+ */
178
+ template <class T>
179
+ constexpr value<T>::value (const T& _value) noexcept
180
+ : value_base_<T>{ _value }
181
+ {
182
+ }
183
+
184
+ // ------------------------------------------------------------------------
185
+
186
+ /**
187
+ * @details
188
+ * Delegates to `value_base_<T>{ _value }` and stores the supplied
189
+ * precision in `epsilon`.
190
+ */
191
+ template <class T>
192
+ requires is_floating_point<T>
193
+ constexpr value<T>::value (const T& _value, const T precision) noexcept
194
+ : value_base_<T>{ _value }, epsilon{ precision }
195
+ {
196
+ }
197
+
198
+ /**
199
+ * @details
200
+ * The epsilon is computed as 1 divided by 10 raised to the number of
201
+ * decimal digits in the value.
202
+ */
203
+ template <class T>
204
+ requires is_floating_point<T>
205
+ constexpr value<T>::value (const T& val)
206
+ : value{ val,
207
+ T (1)
208
+ / math::pow (T (10),
209
+ math::den_size<unsigned long long> (val)) }
210
+ {
211
+ }
212
+
213
+ // ------------------------------------------------------------------------
214
+ } // namespace type_traits
215
+
216
+ // --------------------------------------------------------------------------
217
+ } // namespace micro_os_plus::micro_test_plus
218
+
219
+ #if defined(__GNUC__)
220
+ #pragma GCC diagnostic pop
221
+ #endif
222
+
223
+ // ----------------------------------------------------------------------------
224
+
225
+ #endif // __cplusplus
226
+
227
+ // ----------------------------------------------------------------------------
228
+
229
+ #endif // MICRO_TEST_PLUS_TYPE_TRAITS_INLINES_H_
230
+
231
+ // ----------------------------------------------------------------------------