cpp-toolbox  0.0.1
A toolbox library for C++
Loading...
Searching...
No Matches
type_traits.hpp
Go to the documentation of this file.
1
5#pragma once
6#include <cstddef>
7#include <ostream>
8#include <type_traits>
9
10namespace toolbox
11{
12
13namespace traits
14{
15
16// 版本检测/Version detection
17#if __cplusplus >= 202002L
18# define TOOLBOX_CPP20
19#elif __cplusplus >= 201703L
20# define TOOLBOX_CPP17
21#elif __cplusplus >= 201402L
22# define TOOLBOX_CPP14
23#elif __cplusplus >= 201103L
24# define TOOLBOX_CPP11
25#endif
26
27// 基本类型特征工具/Basic type traits utilities
28namespace detail
29{
34template<typename...>
35using void_t = void;
36
49template<typename T, typename = void>
50struct has_type_impl : std::false_type
51{
52};
53
59template<typename T>
61{
62};
63
87template<typename T>
89{
90 // 检查类型是否可以堆分配/Check if type may be heap allocated
91 static constexpr bool may_be_heap_allocated = !std::is_array_v<T>
92 && (sizeof(T) > 1024
93 || // 大对象可能需要堆分配/Large objects may be heap allocated
94 std::has_virtual_destructor_v<T>
95 || // 虚析构函数暗示动态分配/Virtual destructor implies dynamic
96 // allocation
97 std::is_polymorphic_v<T>); // 多态类型通常在堆上/Polymorphic types
98 // usually on heap
99
100 // 检查类型是否必须堆分配/Check if type must be heap allocated
101 static constexpr bool must_be_heap_allocated =
102 std::is_abstract_v<T>; // 抽象类必须堆分配/Abstract classes must be heap
103 // allocated
104
105 // 检查类型是否可以栈分配/Check if type may be stack allocated
106 static constexpr bool may_be_stack_allocated =
107 !must_be_heap_allocated && std::is_object_v<T> && !std::is_abstract_v<T>;
108};
109} // namespace detail
110
121template<typename T>
123{
124 using type = T;
125};
126
138template<typename T>
140{
141 using type = std::remove_reference_t<T>;
142};
143
144// 特定成员或方法的检测/Detection of specific members or methods
145#ifdef TOOLBOX_CPP17
162template<typename T, typename = void>
163struct has_toString : std::false_type
164{
165};
166
167template<typename T>
168struct has_toString<T, std::void_t<decltype(std::declval<T>().toString())>>
169 : std::true_type
170{
171};
172#else
188template<typename T>
190{
191private:
192 template<typename U>
193 static auto test(int)
194 -> decltype(std::declval<U>().toString(), std::true_type {});
195
196 template<typename>
197 static std::false_type test(...);
198
199public:
200 static constexpr bool value = decltype(test<T>(0))::value;
201};
202#endif
203
216template<typename T>
218{
219 using type =
220 typename std::remove_cv<typename std::remove_reference<T>::type>::type;
221};
222
223// C++17及以上的辅助别名/C++17 and above helper aliases
224#ifdef TOOLBOX_CPP17
236template<typename T>
237using remove_all_qualifiers_t = typename remove_all_qualifiers<T>::type;
238#endif
239
240// 可调用对象检测/Callable detection
241#ifdef TOOLBOX_CPP20
257template<typename T>
258concept Callable = requires(T t) { &T::operator(); };
259#else
275template<typename T, typename = void>
276struct is_callable : std::false_type
277{
278};
279
280template<typename T>
281struct is_callable<T, std::void_t<decltype(&T::operator())>> : std::true_type
282{
283};
284#endif
285
300template<typename... Ts>
302{
303 static constexpr size_t size = sizeof...(Ts);
304};
305
310template<typename T>
312
327template<typename R, typename... Args>
328struct function_traits<R(Args...)>
329{
330 using return_type = R;
331 static constexpr size_t arity = sizeof...(Args);
332
333 template<size_t N>
334 using arg_type = typename std::tuple_element<N, std::tuple<Args...>>::type;
335};
336
355template<typename C, typename R, typename... Args>
356struct function_traits<R (C::*)(Args...)> : function_traits<R(Args...)>
357{
358 using class_type = C;
359};
360
361// SFINAE工具/SFINAE utilities
362#ifdef TOOLBOX_CPP20
375template<typename T>
376concept HasSize = requires(T t) {
377 { t.size() } -> std::convertible_to<std::size_t>;
378};
379
395template<typename T>
396concept Printable = requires(T t, std::ostream& os) {
397 { os << t } -> std::same_as<std::ostream&>;
398};
399#else
412template<typename T, typename = void>
413struct has_size : std::false_type
414{
415};
416
417template<typename T>
418struct has_size<T, std::void_t<decltype(std::declval<T>().size())>>
419 : std::true_type
420{
421};
422
437template<typename T>
439{
440private:
441 template<typename U>
442 static auto test(int)
443 -> decltype(std::declval<std::ostream&>() << std::declval<U>(),
444 std::true_type {});
445
446 template<typename>
447 static std::false_type test(...);
448
449public:
450 static constexpr bool value = decltype(test<T>(0))::value;
451};
452#endif
453
471template<typename EnumType>
473{
474 static_assert(std::is_enum<EnumType>::value,
475 "Template parameter must be an enum type");
476
477public:
478 using underlying_type = typename std::underlying_type<EnumType>::type;
479
480 constexpr enum_wrapper(EnumType value)
481 : value_(value)
482 {
483 }
484
485 constexpr operator EnumType() const { return value_; }
486 constexpr auto to_underlying() const -> underlying_type
487 {
488 return static_cast<underlying_type>(value_);
489 }
490
491private:
492 EnumType value_;
493};
494
495// 编译期类型名称/Compile-time type name
496#ifdef TOOLBOX_CPP17
513template<typename T>
514constexpr std::string_view type_name()
515{
516# if defined(__clang__)
517 constexpr auto prefix = std::string_view {"[T = "};
518 constexpr auto suffix = std::string_view {"]"};
519 constexpr auto function = std::string_view {__PRETTY_FUNCTION__};
520# elif defined(__GNUG__)
521 constexpr auto prefix = std::string_view {"with T = "};
522 constexpr auto suffix = std::string_view {"]"};
523 constexpr auto function = std::string_view {__PRETTY_FUNCTION__};
524# elif defined(_MSC_VER)
525 constexpr auto prefix = std::string_view {"type_name<"};
526 constexpr auto suffix = std::string_view {">(void)"};
527 constexpr auto function = std::string_view {__FUNCSIG__};
528# else
529# error Unsupported compiler
530# endif
531
532 const auto start = function.find(prefix) + prefix.size();
533 const auto end = function.find(suffix);
534 const auto size = end - start;
535 return function.substr(start, size);
536}
537#endif
538
551template<typename T>
557
570template<typename T>
576
577#ifdef TOOLBOX_CPP17
578template<typename T>
579inline constexpr bool is_heap_allocated_v = is_heap_allocated<T>::value;
580
581template<typename T>
582inline constexpr bool is_stack_allocated_v = is_stack_allocated<T>::value;
583#endif
584
595template<typename T>
597{
598 static constexpr bool value = std::is_const_v<T>;
599};
600
601#ifdef TOOLBOX_CPP17
602template<typename T>
603inline constexpr bool is_const_v = is_const<T>::value;
604#endif
605
616template<typename T>
618{
619 static constexpr bool value = std::is_volatile_v<T>;
620};
621
622#ifdef TOOLBOX_CPP17
623template<typename T>
624inline constexpr bool is_volatile_v = is_volatile<T>::value;
625#endif
626
638template<typename T>
640{
641 static constexpr bool value = is_const_v<T> && is_volatile_v<T>;
642};
643
644#ifdef TOOLBOX_CPP17
645template<typename T>
646inline constexpr bool is_const_volatile_v = is_const_volatile<T>::value;
647#endif
648
659template<typename T>
661{
662 static constexpr bool value = std::is_reference_v<T>;
663};
664
665#ifdef TOOLBOX_CPP17
666template<typename T>
667inline constexpr bool is_reference_v = is_reference<T>::value;
668#endif
669
680template<typename T>
682{
683 static constexpr bool value = std::is_array_v<T>;
684};
685
686#ifdef TOOLBOX_CPP17
687template<typename T>
688inline constexpr bool is_array_v = is_array<T>::value;
689#endif
690
702template<typename T>
704{
705 static constexpr bool value = std::is_function_v<T>;
706};
707
708#ifdef TOOLBOX_CPP17
709template<typename T>
710inline constexpr bool is_function_v = is_function<T>::value;
711#endif
712
724template<typename T>
726{
727 static constexpr bool value = std::is_member_pointer_v<T>;
728};
729
730#ifdef TOOLBOX_CPP17
731template<typename T>
732inline constexpr bool is_member_pointer_v = is_member_pointer<T>::value;
733#endif
734
746template<typename T>
748{
749 static constexpr bool value = std::is_pointer_v<T>;
750};
751
752#ifdef TOOLBOX_CPP17
753template<typename T>
754inline constexpr bool is_pointer_v = is_pointer<T>::value;
755#endif
756
767template<typename T>
769{
770 static constexpr bool value = std::is_null_pointer_v<T>;
771};
772
773#ifdef TOOLBOX_CPP17
774template<typename T>
775inline constexpr bool is_null_pointer_v = is_null_pointer<T>::value;
776#endif
777
778// 1. 基础:void_t 实现(C++17 提供,但习惯写出来更清晰)
779template<typename...>
780using void_t = void;
781
782// 2. is_iterable trait:只有当 T 有 begin/end 时才是可迭代的
783template<typename T, typename = void>
784struct is_iterable : std::false_type
785{
786};
787
788template<typename T>
789struct is_iterable<T,
791 decltype(std::end(std::declval<T>()))>>
792 : std::true_type
793{
794};
795
796template<typename T>
797inline constexpr bool is_iterable_v = is_iterable<T>::value;
798
815template<typename T, typename U = T, typename = void>
816struct is_less_than_comparable : std::false_type
817{
818 // 空实现,表示不可比较/Empty implementation, indicates not comparable
819};
820
834template<typename T, typename U>
836 T,
837 U,
838 std::void_t<decltype(std::declval<T>() < std::declval<U>())>>
839 : std::true_type
840{
841 // 当T和U支持<时为true/True if T and U support <
842};
843
857template<typename T, typename U = T>
858inline constexpr bool is_less_than_comparable_v =
860
877template<typename T, typename U = T, typename = void>
878struct is_greater_than_comparable : std::false_type
879{
880 // 空实现,表示不可比较/Empty implementation, indicates not comparable
881};
882
896template<typename T, typename U>
898 T,
899 U,
900 std::void_t<decltype(std::declval<T>() > std::declval<U>())>>
901 : std::true_type
902{
903 // 当T和U支持>时为true/True if T and U support >
904};
905
919template<typename T, typename U = T>
920inline constexpr bool is_greater_than_comparable_v =
922
923} // namespace traits
924} // namespace toolbox
类型安全的枚举包装器/Type-safe enum wrapper
Definition type_traits.hpp:473
constexpr auto to_underlying() const -> underlying_type
Definition type_traits.hpp:486
constexpr enum_wrapper(EnumType value)
Definition type_traits.hpp:480
typename std::underlying_type< EnumType >::type underlying_type
Definition type_traits.hpp:478
void void_t
用于SFINAE的空类型/Empty type for SFINAE
Definition type_traits.hpp:35
constexpr bool is_greater_than_comparable_v
is_greater_than_comparable 的变量模板/Variable template for is_greater_than_comparable
Definition type_traits.hpp:920
constexpr bool is_less_than_comparable_v
is_less_than_comparable 的变量模板/Variable template for is_less_than_comparable
Definition type_traits.hpp:858
void void_t
Definition type_traits.hpp:780
constexpr bool is_iterable_v
Definition type_traits.hpp:797
检查类型是否具有type成员/Check if type has a type member
Definition type_traits.hpp:51
类型存储特征/Storage traits for types
Definition type_traits.hpp:89
static constexpr bool may_be_stack_allocated
Definition type_traits.hpp:106
static constexpr bool must_be_heap_allocated
Definition type_traits.hpp:101
static constexpr bool may_be_heap_allocated
Definition type_traits.hpp:91
R return_type
Definition type_traits.hpp:330
typename std::tuple_element< N, std::tuple< Args... > >::type arg_type
Definition type_traits.hpp:334
C class_type
Definition type_traits.hpp:358
函数特征基础模板/Function traits base template
Definition type_traits.hpp:311
检查类型是否有size成员/Check if type has size member
Definition type_traits.hpp:414
检查类型是否有toString方法(C++17之前版本)/Check if type has toString method (pre-C++17 version)
Definition type_traits.hpp:190
static constexpr bool value
Definition type_traits.hpp:200
检查类型是否为数组/Check if type is an array
Definition type_traits.hpp:682
static constexpr bool value
Definition type_traits.hpp:683
检查类型是否可调用/Check if type is callable
Definition type_traits.hpp:277
检查类型是否同时具有const和volatile限定/Check if type is const-volatile qualified
Definition type_traits.hpp:640
static constexpr bool value
Definition type_traits.hpp:641
检查类型是否为const限定/Check if type is const-qualified
Definition type_traits.hpp:597
static constexpr bool value
Definition type_traits.hpp:598
检查类型是否为函数/Check if type is a function
Definition type_traits.hpp:704
static constexpr bool value
Definition type_traits.hpp:705
检查类型T和U是否支持大于运算符(>)/Check if types T and U support the greater-than operator (>)
Definition type_traits.hpp:879
检查类型是否必须堆分配/Check if type must be heap allocated
Definition type_traits.hpp:553
static constexpr bool value
Definition type_traits.hpp:554
Definition type_traits.hpp:785
检查类型T和U是否支持小于运算符(<)/Check if types T and U support the less-than operator (<)
Definition type_traits.hpp:817
检查类型是否为成员指针/Check if type is a member pointer
Definition type_traits.hpp:726
static constexpr bool value
Definition type_traits.hpp:727
检查类型是否为std::nullptr_t/Check if type is std::nullptr_t
Definition type_traits.hpp:769
static constexpr bool value
Definition type_traits.hpp:770
检查类型是否为指针/Check if type is a pointer
Definition type_traits.hpp:748
static constexpr bool value
Definition type_traits.hpp:749
检查类型是否可打印/Check if type is printable
Definition type_traits.hpp:439
static constexpr bool value
Definition type_traits.hpp:450
检查类型是否为引用/Check if type is a reference
Definition type_traits.hpp:661
static constexpr bool value
Definition type_traits.hpp:662
检查类型是否可以栈分配/Check if type can be stack allocated
Definition type_traits.hpp:572
static constexpr bool value
Definition type_traits.hpp:573
检查类型是否为volatile限定/Check if type is volatile-qualified
Definition type_traits.hpp:618
static constexpr bool value
Definition type_traits.hpp:619
移除类型的所有限定符/Remove all qualifiers from type
Definition type_traits.hpp:218
typename std::remove_cv< typename std::remove_reference< T >::type >::type type
Definition type_traits.hpp:220
移除类型的引用/Remove reference from type
Definition type_traits.hpp:140
std::remove_reference_t< T > type
Definition type_traits.hpp:141
类型标识特征/Type identity trait
Definition type_traits.hpp:123
T type
Definition type_traits.hpp:124
类型列表容器/Type list container
Definition type_traits.hpp:302
static constexpr size_t size
Definition type_traits.hpp:303