micro-test-plus 3.2.0
µTest++, a lightweight testing framework for embedded platforms
Loading...
Searching...
No Matches
type-traits.h
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ distribution.
3 * (https://github.com/micro-os-plus/)
4 * Copyright (c) 2021 Liviu Ionescu. All rights reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software
7 * for any purpose is hereby granted, under the terms of the MIT license.
8 *
9 * If a copy of the license was not distributed with this file, it can
10 * be obtained from <https://opensource.org/licenses/MIT/>.
11 *
12 * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
13 * released under the terms of the Boost Version 1.0 Software License,
14 * which can be obtained from <https://www.boost.org/LICENSE_1_0.txt>.
15 */
16
17#ifndef MICRO_TEST_PLUS_TYPE_TRAITS_H_
18#define MICRO_TEST_PLUS_TYPE_TRAITS_H_
19
20// ----------------------------------------------------------------------------
21
22#ifdef __cplusplus
23
24// ----------------------------------------------------------------------------
25
26#include "math.h"
27
28// ----------------------------------------------------------------------------
29
30#if defined(__GNUC__)
31#pragma GCC diagnostic push
32#if defined(__clang__)
33#pragma clang diagnostic ignored "-Wc++98-compat"
34#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
35#endif
36#endif
37
39{
40 // --------------------------------------------------------------------------
41
46 namespace type_traits
47 {
51 template <class...>
52 struct list
53 {
54 };
55
59 template <class T, class...>
60 struct identity
61 {
62 using type = T;
63 };
64
65#if defined(__DOXYGEN__)
66 // error: Detected potential recursive class relation between class
67 // micro_os_plus::micro_test_plus::type_traits::function_traits and base
68 // class micro_os_plus::micro_test_plus::type_traits::function_traits<
69 // decltype(&T::operator())>!
70 // https://github.com/doxygen/doxygen/issues/9915
71#else
72 template <class T>
73 struct function_traits : function_traits<decltype (&T::operator())>
74 {
75 };
76#endif
77
81 template <class R, class... Args_T>
82 struct function_traits<R (*) (Args_T...)>
83 {
84 using result_type = R;
85 using args = list<Args_T...>;
86 };
87
91 template <class R, class... Args_T>
93 {
94 using result_type = R;
95 using args = list<Args_T...>;
96 };
97
101 template <class R, class T, class... Args_T>
102 struct function_traits<R (T::*) (Args_T...)>
103 {
104 using result_type = R;
105 using args = list<Args_T...>;
106 };
107
111 template <class R, class T, class... Args_T>
112 struct function_traits<R (T::*) (Args_T...) const>
113 {
114 using result_type = R;
115 using args = list<Args_T...>;
116 };
117
118 template <class T>
119 T&&
121 template <class... Ts, class Expr_T>
122 constexpr auto
123 is_valid (Expr_T expr) -> decltype (expr (declval<Ts...> ()), bool ())
124 {
125 return true;
126 }
127
128 template <class...>
129 constexpr auto
130 is_valid (...) -> bool
131 {
132 return false;
133 }
134
135 template <class T>
136 static constexpr auto is_container_v = is_valid<T> (
137 [] (auto t) -> decltype (t.begin (), t.end (), void ()) {});
138
139 template <class T>
140 static constexpr auto has_npos_v
141 = is_valid<T> ([] (auto t) -> decltype (void (t.npos)) {});
142
143 template <class T>
144 static constexpr auto has_value_v
145 = is_valid<T> ([] (auto t) -> decltype (void (t.value)) {});
146
147 template <class T>
148 static constexpr auto has_epsilon_v
149 = is_valid<T> ([] (auto t) -> decltype (void (t.epsilon)) {});
150
151 template <class T>
152 inline constexpr auto is_floating_point_v = false;
153 template <>
154 inline constexpr auto is_floating_point_v<float> = true;
155 template <>
156 inline constexpr auto is_floating_point_v<double> = true;
157 template <>
158 inline constexpr auto is_floating_point_v<long double> = true;
159
160#if defined(__clang__) or defined(_MSC_VER)
161 template <class From, class To>
162 static constexpr auto is_convertible_v = __is_convertible_to (From, To);
163#else
164 template <class From, class To>
165 constexpr auto
166 is_convertible (int) -> decltype (bool (To (declval<From> ())))
167 {
168 return true;
169 }
170 template <class...>
171 constexpr auto
173 {
174 return false;
175 }
176 template <class From, class To>
178#endif
179
183 template <bool>
185 {
186 };
187
191 template <>
193 {
194 using type = int;
195 };
196
197 template <bool Cond>
199
204 struct op
205 {
206 };
207
213 template <auto N>
215 {
216 using value_type = decltype (N);
217 static constexpr auto value = N;
218
219 [[nodiscard]] constexpr auto
220 operator- () const
221 {
222 return integral_constant<-N>{};
223 }
224
225 [[nodiscard]] constexpr explicit
226 operator value_type () const
227 {
228 return N;
229 }
230
231 [[nodiscard]] constexpr auto
232 get () const
233 {
234 return N;
235 }
236 };
237
244 template <class T, auto N, auto D, auto Size, auto P = 1>
246 {
247 using value_type = T;
248
249 static constexpr auto epsilon = T (1) / math::pow (T (10), Size - 1);
250 static constexpr auto value
251 = T (P) * (T (N) + (T (D) / math::pow (T (10), Size)));
252
253 [[nodiscard]] constexpr auto
255 {
256 return floating_point_constant<T, N, D, Size, -1>{};
257 }
258
259 [[nodiscard]] constexpr explicit
260 operator value_type () const
261 {
262 return value;
263 }
264
265 [[nodiscard]] constexpr auto
266 get () const
267 {
268 return value;
269 }
270 };
271
275 template <class T>
277 {
278 using value_type = T;
279
281 {
282 }
283
284 [[nodiscard]] constexpr explicit
285 operator T () const
286 {
287 return value_;
288 }
289
290 [[nodiscard]] constexpr decltype (auto)
291 get () const
292 {
293 return value_;
294 }
295
297 };
298
299 template <class T>
300 inline constexpr auto is_op_v = __is_base_of (type_traits::op, T);
301
306 template <class T, class = int>
308 {
309 using value_type = T;
310
311 constexpr value (const T& _value) : value_{ _value }
312 {
313 }
314
315 [[nodiscard]] constexpr explicit
316 operator T () const
317 {
318 return value_;
319 }
320
321 [[nodiscard]] constexpr decltype (auto)
322 get () const
323 {
324 return value_;
325 }
326
328 };
329
337 template <class T>
338 struct value<T,
339 type_traits::requires_t<type_traits::is_floating_point_v<T>>>
341 {
342 using value_type = T;
343 static inline auto epsilon = T{}; // Why static?
344
345 constexpr value (const T& _value, const T precision) : value_{ _value }
346 {
347 epsilon = precision;
348 }
349
350 constexpr /*explicit(false)*/ value (const T& val)
351 : value{ val,
352 T (1)
353 / math::pow (T (10),
354 math::den_size<unsigned long long> (val)) }
355 {
356 }
357
358 [[nodiscard]] constexpr explicit
359 operator T () const
360 {
361 return value_;
362 }
363
364 [[nodiscard]] constexpr decltype (auto)
365 get () const
366 {
367 return value_;
368 }
369
371 };
372
373 } // namespace type_traits
374
375 // --------------------------------------------------------------------------
376} // namespace micro_os_plus::micro_test_plus
377
378#if defined(__GNUC__)
379#pragma GCC diagnostic pop
380#endif
381
382// ----------------------------------------------------------------------------
383
384#endif // __cplusplus
385
386// ----------------------------------------------------------------------------
387
388#endif // MICRO_TEST_PLUS_TYPE_TRAITS_H_
389
390// ----------------------------------------------------------------------------
constexpr auto pow(const T base, const Exp_T exp) -> T
Generic 'power of', to raise base to exponent (base ^ exp).
Definition math.h:76
typename requires_< Cond >::type requires_t
constexpr auto is_valid(Expr_T expr) -> decltype(expr(declval< Ts... >()), bool())
constexpr auto is_convertible(int) -> decltype(bool(To(declval< From >())))
A generic floating point constant, with custom size and precision. It has a getter and a '-' operator...
A generic integral constant. It has a getter and a '-' operator to return the negative value.
Empty base class of all operators.
Class defining a generic value, accessible via a getter.