Theoretica
Scientific Computing
Loading...
Searching...
No Matches
core_traits.h
Go to the documentation of this file.
1
5
6#ifndef THEORETICA_CORE_TRAITS_H
7#define THEORETICA_CORE_TRAITS_H
8
9#include <type_traits>
10#include <tuple>
11#include "constants.h"
12
13
14namespace theoretica {
15
16
17 // Implement a simple void_t trait in C++14.
18 namespace _internal {
19
20 template<typename ...Args>
21 struct make_void { typedef void type; };
22
23 template<typename ...Args>
24 using void_t = typename make_void<Args...>::type;
25 }
26
27
28 template<typename Type>
29 struct is_real_type : std::is_floating_point<Type> {};
30
31 // Type trait to check whether a type represents
32 // a real number.
33 template<>
34 struct is_real_type<real> : std::true_type {};
35
36
37 // Check whether a structure is orderable,
38 // by checking that it has a comparison operator<().
39 template<typename Structure, typename = _internal::void_t<>>
40 struct is_orderable : std::false_type{};
41
42 // The \internal directive is used to avoid documenting this overload
43 template<typename Structure>
44 struct is_orderable
45 <Structure, _internal::void_t<
46 decltype(std::declval<Structure>() < std::declval<Structure>())>
47 > : std::true_type{};
48
49
50 // Check whether a structure is indexable by a single integer index,
51 // by checking that it has the operator[](0).
52 template<typename Structure, typename = _internal::void_t<>>
53 struct is_indexable : std::false_type{};
54
55 template<typename Structure>
56 struct is_indexable
57 <Structure, _internal::void_t<
58 decltype(std::declval<Structure>()[0])>
59 > : std::true_type{};
60
61
62 // Check whether a structure is iterable,
63 // by checking that it has a method begin().
64 template<typename Structure, typename = _internal::void_t<>>
65 struct is_iterable : std::false_type{};
66
67 template<typename Structure>
68 struct is_iterable
69 <Structure, _internal::void_t<
70 decltype(std::declval<Structure>().begin())>
71 > : std::true_type{};
72
73
74 // Check whether a structure is considerable a vector,
75 // by checking that it has an operator[] and a size() method.
76 template<typename Structure, typename = _internal::void_t<>>
77 struct is_vector : std::false_type{};
78
79 template<typename Structure>
80 struct is_vector
81 <Structure, _internal::void_t<
82 decltype(std::declval<Structure>()[0]),
83 decltype(std::declval<Structure>().size())>
84 > : std::true_type{};
85
86
87#ifdef THEORETICA_HAS_CPP20
88
89 // Concept of a vector-like structure,
90 // which supports random access with operator[]
91 // and has a size() method.
92 template<typename Structure>
93 concept VectorType = requires (Structure v) {
94 v[0];
95 v.size();
96 };
97
98#endif
99
100
101 // Check whether a structure is considerable a matrix,
102 // by checking that it has an operator(), a rows() method
103 // and a cols() method.
104 template<typename Structure, typename = _internal::void_t<>>
105 struct is_matrix : std::false_type{};
106
107 template<typename Structure>
108 struct is_matrix
109 <Structure, _internal::void_t<
110 decltype(std::declval<Structure>()(0, 0)),
111 decltype(std::declval<Structure>().rows()),
112 decltype(std::declval<Structure>().cols())>
113 > : std::true_type{};
114
115
116#ifdef THEORETICA_HAS_CPP20
117
118 // Concept of a matrix-like structure,
119 // which supports random access with operator(i, j)
120 // and has rows() and cols() methods.
121 template<typename Structure>
122 concept MatrixType = requires (Structure v) {
123 v(0, 0);
124 v.rows();
125 v.cols();
126 };
127
128#endif
129
130
131 namespace _internal {
132
133 // Helper structure for vector_element_t
134 template<typename Structure, typename = void>
135 struct vector_element_or_void {
136 using type = void;
137 };
138
139 // Helper structure for vector_element_t
140
141 template<typename Structure>
142 struct vector_element_or_void
143 <Structure, _internal::void_t<decltype(std::declval<Structure&>()[0])>> {
144 using type = std::remove_reference_t<decltype(std::declval<Structure>()[0])>;
145 };
146 }
147
148 // Extract the type of a vector (or any indexable container) from its operator[],
149 // returning void if the type has no operator[].
150 template<typename Structure>
151 using vector_element_or_void_t =
152 typename _internal::vector_element_or_void<Structure>::type;
153
154
155 // Extract the type of a vector (or any indexable container) from its operator[].
156 template<typename Structure>
157 using vector_element_t =
158 std::remove_reference_t<decltype(std::declval<Structure>()[0])>;
159
160
161 // Extract the type of a matrix (or any doubly indexable container) from its operator().
162 template<typename Structure>
163 using matrix_element_t =
164 std::remove_reference_t<decltype(std::declval<Structure>()(0, 0))>;
165
166
167 // Type trait to check whether an indexable container
168 // has elements of the given type.
169 template<typename Structure, typename Type>
170 struct has_type_elements
171 : std::is_same<vector_element_t<Structure>, Type> {};
172
173
174 // Type trait to check whether an indexable container
175 // has real elements.
176 template<typename Structure>
177 using has_real_elements = is_real_type<vector_element_t<Structure>>;
178
179
180 // Enable a function overload if the template typename
181 // is a real number type. The std::enable_if structure is used,
182 // with type T which defaults to bool.
183 template<typename Type, typename T = bool>
184 using enable_real = std::enable_if_t<is_real_type<Type>::value, T>;
185
186
187 // Enable a function overload if the template typename
188 // is considerable a matrix. The std::enable_if structure
189 // is used, with type T which defaults to bool.
190 template<typename Structure, typename T = bool>
191 using enable_matrix = std::enable_if_t<is_matrix<Structure>::value, T>;
192
193
194 // Enable a function overload if the template typename
195 // is considerable a vector. The std::enable_if structure
196 // is used, with type T which defaults to bool.
197 template<typename Structure, typename T = bool>
198 using enable_vector = std::enable_if_t<is_vector<Structure>::value, T>;
199
200
201 // Disable a function overload if the template typename
202 // is considerable a vector. The std::enable_if structure
203 // is used, with type T which defaults to bool.
204 template<typename Structure, typename T = bool>
205 using disable_vector = std::enable_if_t<!is_vector<Structure>::value, T>;
206
207
208 namespace _internal {
209
210 // Helper structure to extract the first type of a variadic template
211 template<typename Arg, typename ...Other>
212 struct get_first {
213 using type = Arg;
214 };
215
216 // Helper structure for is_real_func and related traits
217 template<typename Function, typename T, typename = void>
218 struct return_type_or_void {
219 using type = void;
220 };
221
222 // Helper structure for is_real_func and related traits
223 template<typename Function, typename T>
224 struct return_type_or_void
225 <Function, T, _internal::void_t<decltype(std::declval<Function>()(T(0.0)))>> {
226 using type = decltype(std::declval<Function>()(T(0.0)));
227 };
228
229
230 // Helper structure for extracting information from Callables
231 template <typename T> struct func_helper;
232
233 template <typename R, typename... Args>
234 struct func_helper<R(Args...)> {
235
236 // Return type of the function
237 using return_type = R;
238
239 // Tuple of argument types
240 using args_tuple = std::tuple<Args...>;
241
242 // Type of the first argument
243 using first_arg_type = typename get_first<Args...>::type;
244
245 // Arity of the function (number of arguments)
246 static constexpr std::size_t arity = sizeof...(Args);
247 };
248
249 template <typename R, typename... Args>
250 struct func_helper<R(*)(Args...)> : func_helper<R(Args...)> {};
251
252 template <typename C, typename R, typename... Args>
253 struct func_helper<R(C::*)(Args...) const> : func_helper<R(Args...)> {};
254
255 template <typename T>
256 struct func_helper : func_helper<decltype(&T::operator())> {};
257
258 }
259
260
261 // Type trait to check whether the given function takes
262 // a real number as its first argument.
263 template<typename Function>
264 using is_real_func =
265 std::conditional_t<
266 is_real_type <
267 typename _internal::return_type_or_void<Function, real>::type
268 >::value,
269 std::true_type, std::false_type
270 >;
271
272
273 // Enable a certain function overload if the given type
274 // is a function taking as first argument a real number
275 template<typename Function, typename T = bool>
276 using enable_real_func =
277 typename std::enable_if_t<is_real_func<Function>::value, T>;
278
279
280 // Extract the return type of a Callable object, such as a function
281 // pointer or lambda function.
282 template<typename Function>
283 using return_type_t = typename _internal::func_helper<Function>::return_type;
284
285 // Extract the type of the first argument of a Callable object, such as a function
286 // pointer or lambda function.
287 template<typename Function>
288 using first_arg_t = typename _internal::func_helper<Function>::first_arg_type;
289
290}
291
292#endif
Mathematical constants and default algorithm parameters.
Main namespace of the library which contains all functions and objects.
Definition algebra.h:27
double real
A real number, defined as a floating point type.
Definition constants.h:207