micro-test-plus 5.0.1
µTest++ Testing Framework
Loading...
Searching...
No Matches
type-traits.h
Go to the documentation of this file.
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
47
48#ifndef MICRO_OS_PLUS_MICRO_TEST_PLUS_TYPE_TRAITS_H_
49#define MICRO_OS_PLUS_MICRO_TEST_PLUS_TYPE_TRAITS_H_
50
51// ----------------------------------------------------------------------------
52
53#if defined(__cplusplus)
54
55// ----------------------------------------------------------------------------
56
57#if __has_include("micro-os-plus/project-config.h")
58#include "micro-os-plus/project-config.h"
59#endif // __has_include("micro-os-plus/project-config.h")
60
61#if __has_include("micro-os-plus/micro-test-plus-defines.h")
62#include "micro-os-plus/micro-test-plus-defines.h"
63#endif // __has_include("micro-os-plus/micro-test-plus-defines.h")
64
65#include "math.h"
66
67#include <string_view>
68#include <type_traits>
69
70// ----------------------------------------------------------------------------
71
72#if defined(__GNUC__)
73#pragma GCC diagnostic push
74
75#if defined(__clang__)
76#pragma clang diagnostic ignored "-Wc++98-compat"
77#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
78#endif // defined(__clang__)
79#endif // defined(__GNUC__)
80
81// ============================================================================
82
84{
85 // --------------------------------------------------------------------------
86
111 namespace type_traits
112 {
131 template <class... Types>
132 struct list
133 {
134 };
135
157 template <class T, class... Extra>
158 struct identity
159 {
163 using type = T;
164 };
165
166#if defined(__DOXYGEN__)
167 // error: Detected potential recursive class relation between class
168 // micro_os_plus::micro_test_plus::type_traits::function_traits and base
169 // class micro_os_plus::micro_test_plus::type_traits::function_traits<
170 // decltype(&T::operator())>!
171 // https://github.com/doxygen/doxygen/issues/9915
172#else
193 template <class T>
194 struct function_traits : function_traits<decltype (&T::operator())>
195 {
196 };
197#endif // defined(__DOXYGEN__)
198
218 template <class R, class... Args_T>
219 struct function_traits<R (*) (Args_T...)>
220 {
224 using result_type = R;
225
229 using args = list<Args_T...>;
230 };
231
251 template <class R, class... Args_T>
252 struct function_traits<R (Args_T...)>
253 {
257 using result_type = R;
258
262 using args = list<Args_T...>;
263 };
264
285 template <class R, class T, class... Args_T>
286 struct function_traits<R (T::*) (Args_T...)>
287 {
291 using result_type = R;
292
296 using args = list<Args_T...>;
297 };
298
320 template <class R, class T, class... Args_T>
321 struct function_traits<R (T::*) (Args_T...) const>
322 {
326 using result_type = R;
327
331 using args = list<Args_T...>;
332 };
333
334 // ------------------------------------------------------------------------
335
352 struct op
353 {
354 };
355
356 // ------------------------------------------------------------------------
357 // Concepts.
358
371 template <class T>
372 concept container_like = requires (const T& t) {
373 t.begin ();
374 t.end ();
375 };
376
388 template <class T>
389 concept has_npos = requires { T::npos; };
390
402 template <class T>
403 concept has_value = requires (const T& t) { t.value; };
404
416 template <class T>
417 concept has_epsilon = requires (const T& t) { t.epsilon; };
418
431 template <class T>
432 concept is_floating_point = std::is_floating_point_v<T>;
433
445 template <class T>
446 concept is_op = std::is_base_of_v<type_traits::op, T>;
447
462 template <class Lhs_T, class Rhs_T>
464
478 template <class T>
479 concept checkable = is_op<T> or std::convertible_to<T, bool>;
480
494 template <class T>
495 concept printable = std::is_arithmetic_v<T>
496 or std::is_convertible_v<T, std::string_view>;
497
498 // ------------------------------------------------------------------------
499
517 template <class T>
519 {
523 using value_type = T;
524
530 constexpr explicit value_base_ (const T& v) noexcept;
531
537 [[nodiscard]] constexpr explicit
538 operator T () const noexcept;
539
547 [[nodiscard]] constexpr T
548 get (void) const noexcept;
549
554 };
555
574 template <auto N>
575 struct integral_constant : value_base_<decltype (N)>
576 {
580 static constexpr auto value = N;
581
585 constexpr integral_constant () noexcept;
586
592 [[nodiscard]] constexpr auto
593 operator- () const noexcept;
594 };
595
624 template <class T, auto N, auto D, auto Size, auto P = 1>
626 {
627 static_assert (P == 1 || P == -1,
628 "floating_point_constant: P must be +1 or -1");
629
633 using value_type = T;
634
641 static constexpr auto epsilon = T (1) / math::pow (T (10), Size - 1);
642
649 static constexpr auto value
650 = T (P) * (T (N) + (T (D) / math::pow (T (10), Size)));
651
657 [[nodiscard]] constexpr explicit
658 operator T () const noexcept;
659
667 [[nodiscard]] constexpr T
668 get (void) const noexcept;
669
675 [[nodiscard]] constexpr auto
676 operator- () const noexcept;
677 };
678
691 template <class T>
693 {
699 constexpr genuine_integral_value (const T& _value) noexcept;
700 };
701
715 template <class T>
716 struct value : value_base_<T>
717 {
726 constexpr value (const T& _value) noexcept;
727 };
728
751 template <class T>
752 requires is_floating_point<T>
753 struct value<T> : value_base_<T>
754 {
765 T epsilon = T{};
766
767 // Note: These constructor bodies are defined inline rather than
768 // out-of-line in type-traits-inlines.h. Clang 16 has a deficiency
769 // where it fails to match out-of-line constructor definitions to a
770 // `requires`-constrained partial specialisation: it either rejects
771 // the `requires` clause on the definition as differing from the
772 // declaration, or — when the clause is omitted — incorrectly matches
773 // the definition against the primary template instead of this
774 // specialisation. Keeping the bodies here avoids both failure modes.
775
786 constexpr value (const T& _value, const T precision) noexcept
787 : value_base_<T>{ _value }, epsilon{ precision }
788 {
789 }
790
800 constexpr value (const T& val)
801 : value{ val,
802 T (1)
803 / math::pow (T (10),
804 math::den_size<unsigned long long> (val)) }
805 {
806 }
807 };
808
809 // ------------------------------------------------------------------------
810 } // namespace type_traits
811
812 // --------------------------------------------------------------------------
813} // namespace micro_os_plus::micro_test_plus
814
815#if defined(__GNUC__)
816#pragma GCC diagnostic pop
817#endif // defined(__GNUC__)
818
819// ----------------------------------------------------------------------------
820
821#endif // defined(__cplusplus)
822
823// ============================================================================
824// Templates, inlines & constexpr implementations.
825
827
828// ----------------------------------------------------------------------------
829
830#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TYPE_TRAITS_H_
831
832// ----------------------------------------------------------------------------
C++20 concept satisfied when at least one of two types derives from op.
C++20 concept satisfied when a type can be used as a test expression in expect() or assume().
C++20 concept satisfied when T provides both begin() and end() member functions.
C++20 concept satisfied when T provides an epsilon member.
C++20 concept satisfied when T provides a npos member.
C++20 concept satisfied when T provides a value member.
C++20 concept satisfied when T is a standard floating point type.
C++20 concept satisfied when a type derives from op.
C++20 concept satisfied when a type can be appended to the deferred reporter's output via operator<<.
C++ header file with declarations for the µTest++ mathematical utilities.
Mathematical utilities for the µTest++ testing framework.
constexpr auto pow(const T base, const Exp_T exp) noexcept -> T
Generic exponentiation function to compute the power of a base raised to an exponent.
Type trait utilities and metaprogramming support for the µTest++ testing framework.
Primary namespace for the µTest++ testing framework.
Struct template representing a generic floating point constant with custom size and precision.
static constexpr auto epsilon
The epsilon value used for floating point comparisons.
constexpr T get(void) const noexcept
Getter for the compile-time constant value.
static constexpr auto value
The compile-time constant value.
constexpr genuine_integral_value(const T &_value) noexcept
Constructs a genuine_integral_value with the specified value.
Struct template for compile-time type identity.
static constexpr auto value
The compile-time constant value.
constexpr integral_constant() noexcept
Default constructor. Initialises the base with N.
Struct template representing a compile-time type list.
Empty base struct for all operator types.
T epsilon
The epsilon value used for floating-point comparisons.
constexpr value(const T &val)
Constructs a floating point value with default precision.
constexpr value(const T &_value, const T precision) noexcept
Constructs a floating-point value with a specified precision.
constexpr value_base_(const T &v) noexcept
Constructs a value_base_ with the given value.
constexpr T get(void) const noexcept
Getter for the stored value.
constexpr value(const T &_value) noexcept
Constructs a value object with the specified value.
C++ header file with inline implementations for the µTest++ type trait utilities.