jaulib v1.3.0
Jau Support Library (C++, Java, ..)
type_traits_queries.hpp
Go to the documentation of this file.
1/*
2 * Multiple Authors: Roman Perepelitsa (comp.lang.c++.moderated),
3 * firda (post @ stackoverflow),
4 * Sven Gothel <sgothel@jausoft.com>
5 *
6 * Editor: Sven Gothel <sgothel@jausoft.com>
7 * Copyright (c) 2021 Gothel Software e.K.
8 * Copyright (c) 2021 The Authors (see above)
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining
11 * a copy of this software and associated documentation files (the
12 * "Software"), to deal in the Software without restriction, including
13 * without limitation the rights to use, copy, modify, merge, publish,
14 * distribute, sublicense, and/or sell copies of the Software, and to
15 * permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 */
29
30#ifndef JAU_TYPE_TRAITS_QUERIES_HPP_
31#define JAU_TYPE_TRAITS_QUERIES_HPP_
32
33#include <cstring>
34#include <string>
35#include <cstdint>
36#include <type_traits>
37
38namespace jau {
39
40 /** \addtogroup CppLang
41 *
42 * @{
43 */
44
45 // Author: Sven Gothel
46
47 /**
48 * Enumerating the different groups of type traits
49 */
50 enum class TypeTraitGroup : uint8_t {
51 NONE = 0b00000000,/**< NONE */
52 PRIMARY_TYPE_CAT = 0b00000001,/**< PRIMARY_TYPE_CAT */
53 TYPE_PROPERTIES = 0b00000010,/**< TYPE_PROPERTIES */
54 COMPOSITE_TYPE_CAT = 0b00000100,/**< COMPOSITE_TYPE_CAT */
55 SUPPORTED_OPERATIONS = 0b00001000,/**< SUPPORTED_OPERATIONS */
56 ALL = 0b11111111,/**< ALL */
57 };
58 constexpr uint8_t number(const TypeTraitGroup rhs) noexcept {
59 return static_cast<uint64_t>(rhs);
60 }
61 constexpr TypeTraitGroup operator ^(const TypeTraitGroup lhs, const TypeTraitGroup rhs) noexcept {
62 return static_cast<TypeTraitGroup> ( number(lhs) ^ number(rhs) );
63 }
64 constexpr TypeTraitGroup operator |(const TypeTraitGroup lhs, const TypeTraitGroup rhs) noexcept {
65 return static_cast<TypeTraitGroup> ( number(lhs) | number(rhs) );
66 }
67 constexpr TypeTraitGroup operator &(const TypeTraitGroup lhs, const TypeTraitGroup rhs) noexcept {
68 return static_cast<TypeTraitGroup> ( number(lhs) & number(rhs) );
69 }
70 constexpr bool operator ==(const TypeTraitGroup lhs, const TypeTraitGroup rhs) noexcept {
71 return number(lhs) == number(rhs);
72 }
73 constexpr bool operator !=(const TypeTraitGroup lhs, const TypeTraitGroup rhs) noexcept {
74 return !( lhs == rhs );
75 }
76 constexpr bool isTypeTraitBitSet(const TypeTraitGroup mask, const TypeTraitGroup bit) noexcept {
77 return TypeTraitGroup::NONE != ( mask & bit );
78 }
79
80 /**
81 // *************************************************
82 // *************************************************
83 // *************************************************
84 */
85
86 // Author: Sven Gothel
87
88 /**
89 * Helper, allowing simple access and provision of a typename string representation
90 * at compile time, see jau::type_cue for usage.
91 * <p>
92 * You may use the macro <code>JAU_TYPENAME_CUE(TYPENAME)</code> to set a single type
93 * or maybe <code>JAU_TYPENAME_CUE_ALL(TYPENAME)</code> to set the single type and
94 * all pointer and reference variations (mutable and const).
95 * </p>
96 * <p>
97 * Without user override, implementation will use <code>typeid(T).name()</code>.
98 * </p>
99 * @tparam T the typename to name
100 * @see jau::type_cue
101 */
102 template <typename T>
104 {
105 /**
106 * Return the string representation of this type.
107 * <p>
108 * This might be a compile time user override, see jau::type_name_cue.
109 * </p>
110 * <p>
111 * If no user override has been provides, the default implementation
112 * either returns <code>typeid(T).name()</code> if RTTI is enabled
113 * or <code>"unnamed_type"</code> if RTTI is disabled.
114 * </p>
115 */
116 static const char * name() {
117#if defined(__cxx_rtti_available__)
118 return typeid(T).name();
119#else
120 return "unnamed_type";
121#endif
122 }
123 };
124 /**
125 * Helper, allowing simple access to compile time typename and <i>Type traits</i> information,
126 * see jau::type_name_cue to setup typename's string representation.
127 *
128 * @tparam T the typename to introspect
129 * @see jau::type_name_cue
130 */
131 template <typename T>
132 struct type_cue : public type_name_cue<T>
133 {
134
135 /**
136 * Print information of this type to stdout, potentially with all <i>Type traits</i> known.
137 * @param typedefname the code typedefname (or typename) as a string, should match T
138 * @param verbose if true, prints all <i>Type traits</i> known for this type. Be aware of the long output. Defaults to false.
139 */
140 static void print(const std::string& typedefname, const TypeTraitGroup verbosity=TypeTraitGroup::NONE) {
141 printf("Type: %s -> %s, %zu bytes\n", typedefname.c_str(), type_name_cue<T>::name(), sizeof(T));
142
144 printf(" Primary Type Categories\n");
145 printf(" void %d\n", std::is_void_v<T>);
146 printf(" null ptr %d\n", std::is_null_pointer_v<T>);
147 printf(" integral %d\n", std::is_integral_v<T>);
148 printf(" floating point %d\n", std::is_floating_point_v<T>);
149 printf(" array %d\n", std::is_array_v<T>);
150 printf(" enum %d\n", std::is_enum_v<T>);
151 printf(" union %d\n", std::is_union_v<T>);
152 printf(" class %d\n", std::is_class_v<T>);
153 printf(" function %d\n", std::is_function_v<T>);
154 printf(" pointer %d\n", std::is_pointer_v<T>);
155 printf(" lvalue ref %d\n", std::is_lvalue_reference_v<T>);
156 printf(" rvalue ref %d\n", std::is_rvalue_reference_v<T>);
157 printf(" member obj ptr %d\n", std::is_member_object_pointer_v<T>);
158 printf(" member func ptr %d\n", std::is_member_function_pointer_v<T>);
159 printf("\n");
160 }
162 printf(" Type Properties\n");
163 printf(" const %d\n", std::is_const_v<T>);
164 printf(" volatile %d\n", std::is_volatile_v<T>);
165 printf(" trivial %d\n", std::is_trivial_v<T>);
166 printf(" trivially_copy. %d\n", std::is_trivially_copyable_v<T>);
167 printf(" standard_layout %d\n", std::is_standard_layout_v<T>);
168 printf(" pod %d\n", std::is_standard_layout_v<T> && std::is_trivial_v<T>); // is_pod<>() is deprecated
169 printf(" unique_obj_rep %d\n", std::has_unique_object_representations_v<T>);
170 printf(" empty %d\n", std::is_empty_v<T>);
171 printf(" polymorphic %d\n", std::is_polymorphic_v<T>);
172 printf(" abstract %d\n", std::is_abstract_v<T>);
173 printf(" final %d\n", std::is_final_v<T>);
174 printf(" aggregate %d\n", std::is_aggregate_v<T>);
175 printf(" signed %d\n", std::is_signed_v<T>);
176 printf(" unsigned %d\n", std::is_unsigned_v<T>);
177 #if __cplusplus > 202002L
178 // C++ 23
179 printf(" bounded_array %d\n", std::is_bounded_array_v<T>);
180 printf(" unbounded_array %d\n", std::is_unbounded_array_v<T>);
181 printf(" scoped enum %d\n", std::is_scoped_enum_v<T>);
182 #endif
183 printf("\n");
184 }
186 printf(" Composite Type Categories\n");
187 printf(" fundamental %d\n", std::is_fundamental_v<T>);
188 printf(" arithmetic %d\n", std::is_arithmetic_v<T>);
189 printf(" scalar %d\n", std::is_scalar_v<T>);
190 printf(" object %d\n", std::is_object_v<T>);
191 printf(" compound %d\n", std::is_compound_v<T>);
192 printf(" reference %d\n", std::is_reference_v<T>);
193 printf(" member ptr %d\n", std::is_member_pointer_v<T>);
194 printf("\n");
195 }
197 printf(" Supported Operations\n");
198 printf(" constructible %d {trivially %d, nothrow %d}\n",
199 std::is_constructible_v<T>,
200 std::is_trivially_constructible_v<T>, std::is_nothrow_constructible_v<T>);
201 printf(" default_constructible %d {trivially %d, nothrow %d}\n",
202 std::is_default_constructible_v<T>,
203 std::is_trivially_default_constructible_v<T>, std::is_nothrow_default_constructible_v<T>);
204 printf(" copy_constructible %d {trivially %d, nothrow %d}\n",
205 std::is_copy_constructible_v<T>,
206 std::is_trivially_copy_constructible_v<T>, std::is_nothrow_copy_constructible_v<T>);
207 printf(" move_constructible %d {trivially %d, nothrow %d}\n",
208 std::is_move_constructible_v<T>,
209 std::is_trivially_move_constructible_v<T>, std::is_nothrow_move_constructible_v<T>);
210 printf(" assignable %d {trivially %d, nothrow %d}\n",
211 std::is_assignable_v<T, T>,
212 std::is_trivially_assignable_v<T, T>, std::is_nothrow_assignable_v<T, T>);
213 printf(" copy_assignable %d {trivially %d, nothrow %d}\n",
214 std::is_copy_assignable_v<T>,
215 std::is_trivially_copy_assignable_v<T>, std::is_nothrow_copy_assignable_v<T>);
216 printf(" move_assignable %d {trivially %d, nothrow %d}\n",
217 std::is_move_assignable_v<T>,
218 std::is_trivially_move_assignable_v<T>, std::is_nothrow_move_assignable_v<T>);
219 printf(" destructible %d {trivially %d, nothrow %d, virtual %d}\n",
220 std::is_destructible_v<T>,
221 std::is_trivially_destructible_v<T>, std::is_nothrow_destructible_v<T>,
222 std::has_virtual_destructor_v<T>);
223 printf(" swappable %d {nothrow %d}\n",
224 std::is_swappable_v<T>, std::is_nothrow_swappable_v<T>);
225 }
226 }
227 };
228 #define JAU_TYPENAME_CUE(A) template<> struct jau::type_name_cue<A> { static const char * name() { return #A; } };
229 #define JAU_TYPENAME_CUE_ALL(A) JAU_TYPENAME_CUE(A) JAU_TYPENAME_CUE(A*) JAU_TYPENAME_CUE(const A*) JAU_TYPENAME_CUE(A&) JAU_TYPENAME_CUE(const A&)
230
231 /**
232 // *************************************************
233 // *************************************************
234 // *************************************************
235 */
236
237 // Author: Sven Gothel
238
239 /**
240 * <code>template< class T > is_container_memmove_compliant<T>::value</code> compile-time Type Trait,
241 * determining whether the given template class claims to be container memmove compliant, see @Ref darray_memmove.
242 */
243 template< class, class = void >
244 struct is_container_memmove_compliant : std::false_type { };
245
246 /**
247 * <code>template< class T > is_container_memmove_compliant<T>::value</code> compile-time Type Trait,
248 * determining whether the given template class claims to be container memmove compliant, see @Ref darray_memmove.
249 */
250 template< class T >
251 struct is_container_memmove_compliant<T, std::void_t<typename T::container_memmove_compliant>> : T::container_memmove_compliant { };
252
254
255 /**
256 * <code>template< class T > is_enforcing_secmem<T>::value</code> compile-time Type Trait,
257 * determining whether the given template class enforces secmem, see @Ref darray_secmem.
258 */
259 template< class, class = void >
260 struct is_enforcing_secmem : std::false_type { };
261
262 /**
263 * <code>template< class T > is_enforcing_secmem<T>::value</code> compile-time Type Trait,
264 * determining whether the given template class enforces secmem, see @Ref darray_secmem.
265 */
266 template< class T >
267 struct is_enforcing_secmem<T, std::void_t<typename T::enforce_secmem>> : T::enforce_secmem { };
268
269 template <typename T> inline constexpr bool is_enforcing_secmem_v = is_enforcing_secmem<T>::value;
270
271
272 /**
273 // *************************************************
274 // *************************************************
275 // *************************************************
276 */
277
278 // Author: firda @ stackoverflow (posted the following there)
279 // Location: https://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions/25448020#25448020
280#if 0
281 /// Checker for typedef with given name and convertible type
282 #define TYPEDEF_CHECKER(checker, name) \
283 template<class C, typename T, typename = void> struct checker : std::false_type {}; \
284 template<class C, typename T> struct checker<C, T, typename std::enable_if< \
285 std::is_convertible<typename C::name, T>::value>::type> : std::true_type {}
286
287 /// Checker for typedef with given name and exact type
288 #define TYPEDEF_CHECKER_STRICT(checker, name) \
289 template<class C, typename T, typename = void> struct checker : std::false_type {}; \
290 template<class C, typename T> struct checker<C, T, typename std::enable_if< \
291 std::is_same<typename C::name, T>::value>::type> : std::true_type {}
292
293 /// Checker for typedef with given name and any type
294 #define TYPEDEF_CHECKER_ANY(checker, name) \
295 template<class C, typename = void> struct checker : std::false_type {}; \
296 template<class C> struct checker<C, typename std::enable_if< \
297 !std::is_same<typename C::name*, void>::value>::type> : std::true_type {}
298
299 /// Checker for static const variable with given name and value
300 #define MVALUE_CHECKER(checker, name, val) \
301 template<class C, typename = void> struct checker : std::false_type {}; \
302 template<class C> struct checker<C, typename std::enable_if< \
303 std::is_convertible<decltype(C::name), const decltype(val)>::value && C::name == val>::type> : std::true_type {}
304 /// Checker for static const variable with given name, value and type
305 #define MVALUE_CHECKER_STRICT(checker, name, val) \
306 template<class C, typename = void> struct checker : std::false_type {}; \
307 template<class C> struct checker<C, typename std::enable_if< \
308 std::is_same<decltype(C::name), const decltype(val)>::value && C::name == val>::type> : std::true_type {}
309#endif
310
311 /// Checker for member with given name and convertible type
312 #define MTYPE_CHECKER(checker, name) \
313 template<class C, typename T, typename = void> struct checker : std::false_type {}; \
314 template<class C, typename T> struct checker<C, T, typename std::enable_if< \
315 std::is_convertible<decltype(C::name), T>::value>::type> : std::true_type {}
316
317 /// Checker for member with given name and exact type
318 #define MTYPE_CHECKER_STRICT(checker, name) \
319 template<class C, typename T, typename = void> struct checker : std::false_type {}; \
320 template<class C, typename T> struct checker<C, T, typename std::enable_if< \
321 std::is_same<decltype(C::name), T>::value>::type> : std::true_type {}
322
323 /// Checker for member with given name and any type
324 #define MTYPE_CHECKER_ANY(checker, name) \
325 template<class C, typename = void> struct checker : std::false_type {}; \
326 template<class C> struct checker<C, typename std::enable_if< \
327 !std::is_same<decltype(C::name)*, void>::value>::type> : std::true_type {}
328
329 /// Checker for member function with convertible return type and accepting given arguments
330 #define METHOD_CHECKER(checker, name, ret, args) \
331 template<class C, typename=void> struct checker : std::false_type {}; \
332 template<class C> struct checker<C, typename std::enable_if< \
333 std::is_convertible<decltype(std::declval<C>().name args), ret>::value>::type> : std::true_type {};
334
335 /// Checker for member function with exact retutn type and accepting given arguments
336 #define METHOD_CHECKER_STRICT_RET(name, fn, ret, args) \
337 template<class C, typename=void> struct name : std::false_type {}; \
338 template<class C> struct name<C, typename std::enable_if< \
339 std::is_same<decltype(std::declval<C>().fn args), ret>::value>::type> : std::true_type {};
340
341 /// Checker for member function accepting given arguments
342 #define METHOD_CHECKER_ANY(name, fn, args) \
343 template<class C, typename=void> struct name : std::false_type {}; \
344 template<class C> struct name<C, typename std::enable_if< \
345 !std::is_same<decltype(std::declval<C>().fn args)*, void>::value>::type> : std::true_type {};
346
347 METHOD_CHECKER(has_toString, toString, std::string, ())
348 template <typename _Tp> inline constexpr bool has_toString_v = has_toString<_Tp>::value;
349
350 METHOD_CHECKER(has_to_string, to_string, std::string, ())
351 template <typename _Tp> inline constexpr bool has_to_string_v = has_to_string<_Tp>::value;
352
353 // Author: Sven Gothel
354
355 /// Checker for member of pointer '->' operator with convertible pointer return, no arguments
356 template<class C, typename=void> struct has_member_of_pointer : std::false_type {};
357 template<class C> struct has_member_of_pointer<C, typename std::enable_if<
358 std::is_pointer<decltype(std::declval<C>().operator->())>::value>::type> : std::true_type {};
359
360 template <typename _Tp> inline constexpr bool has_member_of_pointer_v = has_member_of_pointer<_Tp>::value;
361
362 /**@}*/
363
364} // namespace jau
365
366/** \example test_type_traits_queries01.cpp
367 * This C++ unit test validates the jau::has_toString and other type traints queries
368 */
369
370#endif /* JAU_TYPE_TRAITS_QUERIES_HPP_ */
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
constexpr bool isTypeTraitBitSet(const TypeTraitGroup mask, const TypeTraitGroup bit) noexcept
constexpr bool has_toString_v
constexpr TypeTraitGroup operator&(const TypeTraitGroup lhs, const TypeTraitGroup rhs) noexcept
constexpr bool has_member_of_pointer_v
constexpr bool has_to_string_v
constexpr bool is_container_memmove_compliant_v
constexpr bool is_enforcing_secmem_v
#define METHOD_CHECKER(checker, name, ret, args)
Checker for member function with convertible return type and accepting given arguments.
TypeTraitGroup
Enumerating the different groups of type traits.
constexpr TypeTraitGroup operator^(const TypeTraitGroup lhs, const TypeTraitGroup rhs) noexcept
constexpr TypeTraitGroup operator|(const TypeTraitGroup lhs, const TypeTraitGroup rhs) noexcept
@ SUPPORTED_OPERATIONS
SUPPORTED_OPERATIONS.
@ PRIMARY_TYPE_CAT
PRIMARY_TYPE_CAT.
@ TYPE_PROPERTIES
TYPE_PROPERTIES.
@ COMPOSITE_TYPE_CAT
COMPOSITE_TYPE_CAT.
constexpr uint32_t number(const func::target_type rhs) noexcept
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32
bool operator==(const callocator< T1 > &lhs, const callocator< T2 > &rhs) noexcept
Definition: callocator.hpp:150
bool operator!=(const callocator< T1 > &lhs, const callocator< T2 > &rhs) noexcept
Definition: callocator.hpp:163
STL namespace.
Checker for member of pointer '->' operator with convertible pointer return, no arguments.
template< class T > is_container_memmove_compliant<T>::value compile-time Type Trait,...
template< class T > is_enforcing_secmem<T>::value compile-time Type Trait, determining whether the gi...
Helper, allowing simple access to compile time typename and Type traits information,...
static void print(const std::string &typedefname, const TypeTraitGroup verbosity=TypeTraitGroup::NONE)
Print information of this type to stdout, potentially with all Type traits known.
Helper, allowing simple access and provision of a typename string representation at compile time,...
static const char * name()
Return the string representation of this type.
int printf(const char *format,...)
Operating Systems predefined macros.