C++ Utilities 5.27.0
Useful C++ classes and routines such as argument parser, IO and conversion utilities
Loading...
Searching...
No Matches
traits.h
Go to the documentation of this file.
1#ifndef CPP_UTILITIES_TRAITS_H
2#define CPP_UTILITIES_TRAITS_H
3
4#include <iterator>
5#include <string>
6#include <type_traits>
7
8namespace CppUtilities {
9
11namespace Traits {
12
14namespace Detail {
15enum class Enabler {};
16}
18
20template <typename If, typename Then, typename Else> using Conditional = typename std::conditional<If::value, Then, Else>::type;
21
23template <bool B, typename...> struct Bool : std::integral_constant<bool, B> {};
24
26template <typename T> using Not = Bool<!T::value>;
27
29template <typename... T> struct Any : Bool<false> {};
31template <typename Head, typename... Tail> struct Any<Head, Tail...> : Conditional<Head, Bool<true>, Any<Tail...>> {};
32
34template <typename... T> struct All : Bool<true> {};
36template <typename Head, typename... Tail> struct All<Head, Tail...> : Conditional<Head, All<Tail...>, Bool<false>> {};
37
39template <typename... T> struct None : Bool<true> {};
41template <typename Head, typename... Tail> struct None<Head, Tail...> : Conditional<Head, Bool<false>, None<Tail...>> {};
42
44template <typename... Condition> using EnableIf = typename std::enable_if<All<Condition...>::value, Detail::Enabler>::type;
46template <typename... Condition> using DisableIf = typename std::enable_if<!All<Condition...>::value, Detail::Enabler>::type;
47
49template <typename... Condition> using EnableIfAny = typename std::enable_if<Any<Condition...>::value, Detail::Enabler>::type;
51template <typename... Condition> using DisableIfAny = typename std::enable_if<!Any<Condition...>::value, Detail::Enabler>::type;
52
54namespace Detail {
55template <typename T, template <typename...> class Template> struct IsSpecializationOfHelper : Bool<false> {};
56template <template <typename...> class Template, typename... Args> struct IsSpecializationOfHelper<Template<Args...>, Template> : Bool<true> {};
57} // namespace Detail
60template <typename Type, template <typename...> class... TemplateTypes>
62 : Detail::IsSpecializationOfHelper<typename std::remove_cv<typename std::remove_reference<Type>::type>::type, TemplateTypes...> {};
64template <typename Type, template <typename...> class... TemplateTypes> struct IsSpecializingAnyOf : Bool<false> {};
66template <typename Type, template <typename...> class TemplateType, template <typename...> class... RemainingTemplateTypes>
67struct IsSpecializingAnyOf<Type, TemplateType, RemainingTemplateTypes...>
68 : Conditional<IsSpecializationOf<Type, TemplateType>, Bool<true>, IsSpecializingAnyOf<Type, RemainingTemplateTypes...>> {};
69
71template <typename... T> struct IsAnyOf : Bool<false> {};
73template <typename Type, typename OtherType, typename... RemainingTypes>
74struct IsAnyOf<Type, OtherType, RemainingTypes...> : Conditional<std::is_same<Type, OtherType>, Bool<true>, IsAnyOf<Type, RemainingTypes...>> {};
76template <typename... T> struct IsNoneOf : Bool<true> {};
78template <typename Type, typename OtherType, typename... RemainingTypes>
79struct IsNoneOf<Type, OtherType, RemainingTypes...> : Conditional<std::is_same<Type, OtherType>, Bool<false>, IsNoneOf<Type, RemainingTypes...>> {};
80
82template <typename T>
84 : Bool<std::is_same<char const *, typename std::decay<T>::type>::value || std::is_same<char *, typename std::decay<T>::type>::value> {};
87template <typename T>
89 : Bool<IsCString<T>::value || IsSpecializationOf<T, std::basic_string>::value || IsSpecializationOf<T, std::basic_string_view>::value> {};
90
92template <typename T, typename = void> struct IsComplete : Bool<false> {};
94template <typename T> struct IsComplete<T, decltype(void(sizeof(T)))> : Bool<true> {};
95
100#define CPP_UTILITIES_PP_COMMA ,
101
108#define CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(CheckName, CheckCode) \
109 namespace Detail { \
110 template <typename T> auto CheckName(int) -> decltype(CheckCode, ::CppUtilities::Traits::Bool<true>{}); \
111 template <typename T>::CppUtilities::Traits::Bool<false> CheckName(...); \
112 } \
113 template <typename T> using CheckName = decltype(Detail::CheckName<T>(0))
114
116CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(IsDereferencable, *(std::declval<T &>()));
117
119CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(HasSize, std::is_integral<decltype(std::declval<T &>().size())>::value);
120
122CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(IsReservable, std::declval<T &>().reserve(0u));
123
125CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(IsResizable, std::declval<T &>().resize(0u));
126
128CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(HasOperatorBool, std::declval<T &>() ? true : false);
129
132 // begin/end and operator !=
133 std::begin(std::declval<T &>())
134 != std::end(std::declval<T &>()) CPP_UTILITIES_PP_COMMA
135 // operator ,
137 // operator ++
138 ++ std::declval<decltype(begin(std::declval<T &>())) &>() CPP_UTILITIES_PP_COMMA
139 // operator*
140 void(*begin(std::declval<T &>())));
141
143template <typename T, EnableIf<IsDereferencable<T>> * = nullptr> constexpr auto &dereferenceMaybe(T &&value)
144{
145 return *value;
146}
147
149template <typename T, DisableIf<IsDereferencable<T>> * = nullptr> constexpr auto &dereferenceMaybe(T &&value)
150{
151 return value;
152}
153
154} // namespace Traits
155
156} // namespace CppUtilities
157
158#endif // CPP_UTILITIES_TRAITS_H
typename std::enable_if<!All< Condition... >::value, Detail::Enabler >::type DisableIf
Shortcut for std::enable_if to negate the condition and omit ::value and ::type.
Definition traits.h:46
typename std::enable_if< Any< Condition... >::value, Detail::Enabler >::type EnableIfAny
Shortcut for std::enable_if to apply Traits::Any and omit ::value and ::type.
Definition traits.h:49
constexpr auto & dereferenceMaybe(T &&value)
Dereferences the specified value if possible; otherwise just returns value itself.
Definition traits.h:143
typename std::conditional< If::value, Then, Else >::type Conditional
Shortcut for std::conditional to omit ::value and ::type.
Definition traits.h:20
typename std::enable_if< All< Condition... >::value, Detail::Enabler >::type EnableIf
Shortcut for std::enable_if to omit ::value and ::type.
Definition traits.h:44
typename std::enable_if<!Any< Condition... >::value, Detail::Enabler >::type DisableIfAny
Shortcut for std::enable_if to apply Traits::Any, negate the condition and omit ::value and ::type.
Definition traits.h:51
Contains all utilities provides by the c++utilities library.
Evaluates to Bool<true> if all specified conditions are true; otherwise evaluates to Bool<false>.
Definition traits.h:34
Evaluates to Bool<true> if at least one of the specified conditions is true; otherwise evaluates to B...
Definition traits.h:29
Wraps a static boolean constant.
Definition traits.h:23
Evaluates to Bool<true> if the specified type is any of the specified types; otherwise evaluates to B...
Definition traits.h:71
Evaluates to Bool<true> if the specified type is a C-string (char * or const char *); otherwise evalu...
Definition traits.h:84
Evaluates to Bool<true> if the specified type is complete; if the type is only forward-declared it ev...
Definition traits.h:92
Evaluates to Bool<true> if the specified type is none of the specified types; otherwise evaluates to ...
Definition traits.h:76
Evaluates to Bool<true> if the specified type is based on the specified template; otherwise evaluates...
Definition traits.h:62
Evaluates to Bool<true> if the specified type is based on one of the specified templates; otherwise e...
Definition traits.h:64
Evaluates to Bool<true> if the specified type is a standard string, standard string view or C-string ...
Definition traits.h:89
Evaluates to Bool<true> if none of the specified conditions are true; otherwise evaluates to Bool<fal...
Definition traits.h:39
#define CPP_UTILITIES_PP_COMMA
The CPP_UTILITIES_PP_COMMA macro helps passing "," as a macro argument.
Definition traits.h:100
#define CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(CheckName, CheckCode)
The CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK macro defines a type trait for checking whether some opera...
Definition traits.h:108