Dune Core Modules (2.6.0)

typetraits.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_TYPETRAITS_HH
4#define DUNE_TYPETRAITS_HH
5
6#include <complex>
7#include <type_traits>
8#include <utility>
9
11
12namespace Dune
13{
14
15 namespace Impl
16 {
18
27 template <class...>
28 struct voider
29 {
30 using type = void;
31 };
32 }
33
35
38 template <class... Types>
39 using void_t = typename Impl::voider<Types...>::type;
40
54 struct Empty {};
55
62 template<class T1, class T2>
64 {
65 enum {
70 value = std::is_convertible<T1,T2>::value || std::is_convertible<T2,T1>::value
71 };
72 };
73
79 template<class T1, class T2, class Type>
81 : public std::enable_if<IsInteroperable<T1,T2>::value, Type>
82 {};
83
101
117
124 template<typename T>
125 struct AlwaysFalse {
127 static const bool value = false;
128 };
129
137 template<typename T>
138 struct AlwaysTrue {
140 static const bool value = true;
141 };
142
145
160 template <typename T>
161 struct IsNumber
162 : public std::integral_constant<bool, std::is_arithmetic<T>::value> {
163 };
164
165#ifndef DOXYGEN
166
167 template <typename T>
168 struct IsNumber<std::complex<T>>
169 : public std::integral_constant<bool, IsNumber<T>::value> {
170 };
171
172#endif // DOXYGEN
173
174
176
179 template <typename T>
180 struct has_nan
181 : public std::integral_constant<bool, std::is_floating_point<T>::value> {
182 };
183
184#ifndef DOXYGEN
185
186 template <typename T>
187 struct has_nan<std::complex<T>>
188 : public std::integral_constant<bool, std::is_floating_point<T>::value> {
189 };
190
191#endif // DOXYGEN
192
193
194#if defined(DOXYGEN) or HAVE_IS_INDEXABLE_SUPPORT
195
196#ifndef DOXYGEN
197
198 namespace Impl {
199
200 template<typename T, typename I, typename = int>
201 struct _is_indexable
202 : public std::false_type
203 {};
204
205 template<typename T, typename I>
206 struct _is_indexable<T,I,typename std::enable_if<(sizeof(std::declval<T>()[std::declval<I>()]) > 0),int>::type>
207 : public std::true_type
208 {};
209
210 }
211
212#endif // DOXYGEN
213
215
219 template<typename T, typename I = std::size_t>
221 : public Impl::_is_indexable<T,I>
222 {};
223
224
225#else // defined(DOXYGEN) or HAVE_IS_INDEXABLE_SUPPORT
226
227
228 // okay, here follows a mess of compiler bug workarounds...
229 // GCC 4.4 dies if we try to subscript a simple type like int and
230 // both GCC 4.4 and 4.5 don't like using arbitrary types as subscripts
231 // for macros.
232 // So we make sure to only ever attempt the SFINAE for operator[] for
233 // class types, and to make sure the compiler doesn't become overly eager
234 // we have to do some lazy evaluation tricks with nested templates and
235 // stuff.
236 // Let's get rid of GCC 4.4 ASAP!
237
238
239 namespace Impl {
240
241 // simple wrapper template to support the lazy evaluation required
242 // in _is_indexable
243 template<typename T>
244 struct _lazy
245 {
246 template<typename U>
247 struct evaluate
248 {
249 typedef T type;
250 };
251 };
252
253 // default version, gets picked if SFINAE fails
254 template<typename T, typename = int>
255 struct _is_indexable
256 : public std::false_type
257 {};
258
259 // version for types supporting the subscript operation
260 template<typename T>
261 struct _is_indexable<T,decltype(std::declval<T>()[0],0)>
262 : public std::true_type
263 {};
264
265 // helper struct for delaying the evaluation until we are sure
266 // that T is a class (i.e. until we are outside std::conditional
267 // below)
268 struct _check_for_index_operator
269 {
270
271 template<typename T>
272 struct evaluate
273 : public _is_indexable<T>
274 {};
275
276 };
277
278 }
279
280 // The rationale here is as follows:
281 // 1) If we have an array, we assume we can index into it. That isn't
282 // true if I isn't an integral type, but that's why we have the static assertion
283 // in the body - we could of course try and check whether I is integral, but I
284 // can't be arsed and want to provide a motivation to switch to a newer compiler...
285 // 2) If we have a class, we use SFINAE to check for operator[]
286 // 3) Otherwise, we assume that T does not support indexing
287 //
288 // In order to make sure that the compiler doesn't accidentally try the SFINAE evaluation
289 // on an array or a scalar, we have to resort to lazy evaluation.
290 template<typename T, typename I = std::size_t>
291 struct is_indexable
292 : public std::conditional<
293 std::is_array<T>::value,
294 Impl::_lazy<std::true_type>,
295 typename std::conditional<
296 std::is_class<T>::value,
297 Impl::_check_for_index_operator,
298 Impl::_lazy<std::false_type>
299 >::type
300 >::type::template evaluate<T>::type
301 {
302 static_assert(std::is_same<I,std::size_t>::value,"Your compiler is broken and does not support checking for arbitrary index types");
303 };
304
305
306#endif // defined(DOXYGEN) or HAVE_IS_INDEXABLE_SUPPORT
307
308#ifndef DOXYGEN
309
310 namespace Impl {
311 // This function does nothing.
312 // By passing expressions to this function one can avoid
313 // "value computed is not used" warnings that may show up
314 // in a comma expression.
315 template<class...T>
316 void ignore(T&&... /*t*/)
317 {}
318 }
319
320#endif // DOXYGEN
321
325 // default version, gets picked if SFINAE fails
326 template<typename T, typename = void>
327 struct is_range
328 : public std::false_type
329 {};
330
331#ifndef DOXYGEN
332 // version for types with begin() and end()
333 template<typename T>
334 struct is_range<T, decltype(Impl::ignore(
335 std::declval<T>().begin(),
336 std::declval<T>().end(),
337 std::declval<T>().begin() != std::declval<T>().end(),
338 decltype(std::declval<T>().begin()){std::declval<T>().end()},
339 ++(std::declval<std::add_lvalue_reference_t<decltype(std::declval<T>().begin())>>()),
340 *(std::declval<T>().begin())
341 ))>
342 : public std::true_type
343 {};
344#endif
345
346#ifndef DOXYGEN
347 // this is just a forward declaration
348 template <class> struct FieldTraits;
349#endif
350
352 template <class Type>
353 using field_t = typename FieldTraits<Type>::field_type;
354
356 template <class Type>
357 using real_t = typename FieldTraits<Type>::real_type;
358
359
360#ifndef DOXYGEN
361
362 // Implementation of IsTuple
363 namespace Impl {
364
365 template<class T>
366 struct IsTuple : public std::false_type
367 {};
368
369 template<class... T>
370 struct IsTuple<std::tuple<T...>> : public std::true_type
371 {};
372
373 } // namespace Impl
374
375#endif // DOXYGEN
376
382 template<class T>
383 struct IsTuple :
384 public Impl::IsTuple<T>
385 {};
386
387
388#ifndef DOXYGEN
389
390 // Implementation of IsTupleOrDerived
391 namespace Impl {
392
393 template<class... T, class Dummy>
394 std::true_type isTupleOrDerived(const std::tuple<T...>*, Dummy)
395 { return {}; }
396
397 template<class Dummy>
398 std::false_type isTupleOrDerived(const void*, Dummy)
399 { return {}; }
400
401 } // namespace Impl
402
403#endif // DOXYGEN
404
410 template<class T>
412 public decltype(Impl::isTupleOrDerived(std::declval<T*>(), true))
413 {};
414
415
416#ifndef DOXYGEN
417
418 // Implementation of is IsIntegralConstant
419 namespace Impl {
420
421 template<class T>
422 struct IsIntegralConstant : public std::false_type
423 {};
424
425 template<class T, T t>
426 struct IsIntegralConstant<std::integral_constant<T, t>> : public std::true_type
427 {};
428
429 } // namespace Impl
430
431#endif // DOXYGEN
432
438 template<class T>
439 struct IsIntegralConstant : public Impl::IsIntegralConstant<std::decay_t<T>>
440 {};
441
442
443
457 template<typename... T>
458 struct SizeOf
459 : public std::integral_constant<std::size_t,sizeof...(T)>
460 {};
461
462
463#ifndef DOXYGEN
464
465 namespace Impl {
466
467 template<class T, T...>
468 struct IntegerSequenceHelper;
469
470 // Helper struct to compute the i-th entry of a std::integer_sequence
471 //
472 // This could also be implemented using std::get<index>(std::make_tuple(t...)).
473 // However, the gcc-6 implementation of std::make_tuple increases the instantiation
474 // depth by 15 levels for each argument, such that the maximal instantiation depth
475 // is easily hit, especially with clang where it is set to 256.
476 template<class T, T head, T... tail>
477 struct IntegerSequenceHelper<T, head, tail...>
478 {
479
480 // get first entry
481 static constexpr auto get(std::integral_constant<std::size_t, 0>)
482 {
483 return std::integral_constant<T, head>();
484 }
485
486 // call get with first entry cut off and decremented index
487 template<std::size_t index,
488 std::enable_if_t<(index > 0) and (index < sizeof...(tail)+1), int> = 0>
489 static constexpr auto get(std::integral_constant<std::size_t, index>)
490 {
491 return IntegerSequenceHelper<T, tail...>::get(std::integral_constant<std::size_t, index-1>());
492 }
493
494 // use static assertion if index exceeds size
495 template<std::size_t index,
496 std::enable_if_t<(index >= sizeof...(tail)+1), int> = 0>
497 static constexpr auto get(std::integral_constant<std::size_t, index>)
498 {
499 static_assert(index < sizeof...(tail)+1, "index used in IntegerSequenceEntry exceed size");
500 }
501 };
502
503 } // end namespace Impl
504
505#endif // DOXYGEN
506
507
517 template<class T, T... t, std::size_t index>
518 constexpr auto integerSequenceEntry(std::integer_sequence<T, t...> /*seq*/, std::integral_constant<std::size_t, index> i)
519 {
520 static_assert(index < sizeof...(t), "index used in IntegerSequenceEntry exceed size");
521 return Impl::IntegerSequenceHelper<T, t...>::get(i);
522 }
523
524
531 template<class IntegerSequence, std::size_t index>
533
534#ifndef DOXYGEN
535
536 template<class T, T... t, std::size_t i>
537 struct IntegerSequenceEntry<std::integer_sequence<T, t...>, i>
538 : public decltype(Impl::IntegerSequenceHelper<T, t...>::get(std::integral_constant<std::size_t, i>()))
539 {};
540
541#endif // DOXYGEN
542
544}
545#endif
Definition of the DUNE_DEPRECATED macro for the case that config.h is not available.
constexpr auto integerSequenceEntry(std::integer_sequence< T, t... >, std::integral_constant< std::size_t, index > i)
Get entry of std::integer_sequence.
Definition: typetraits.hh:518
typename FieldTraits< Type >::real_type real_t
Convenient access to FieldTraits<Type>::real_type.
Definition: typetraits.hh:357
typename Impl::voider< Types... >::type void_t
Is void for all valid input types (see N3911). The workhorse for C++11 SFINAE-techniques.
Definition: typetraits.hh:39
typename FieldTraits< Type >::field_type field_t
Convenient access to FieldTraits<Type>::field_type.
Definition: typetraits.hh:353
Dune namespace.
Definition: alignedallocator.hh:10
STL namespace.
template which always yields a false value
Definition: typetraits.hh:125
static const bool value
always a false value
Definition: typetraits.hh:127
template which always yields a true value
Definition: typetraits.hh:138
static const bool value
always a true value
Definition: typetraits.hh:140
Just an empty class.
Definition: typetraits.hh:54
Enable typedef if two types are interoperable.
Definition: typetraits.hh:82
Get entry of std::integer_sequence.
Definition: typetraits.hh:532
Check if T is an std::integral_constant<I, i>
Definition: typetraits.hh:440
Checks whether two types are interoperable.
Definition: typetraits.hh:64
@ value
True if either a conversion from T1 to T2 or vice versa exists.
Definition: typetraits.hh:70
Whether this type acts as a scalar in the context of (hierarchically blocked) containers.
Definition: typetraits.hh:162
Check if T derived from a std::tuple<...>
Definition: typetraits.hh:413
Check if T is a std::tuple<...>
Definition: typetraits.hh:385
Compute size of variadic type list.
Definition: typetraits.hh:460
Whether this type has a value of NaN.
Definition: typetraits.hh:181
Type trait to determine whether an instance of T has an operator[](I), i.e. whether it can be indexed...
Definition: typetraits.hh:222
typetrait to check that a class has begin() and end() members
Definition: typetraits.hh:329
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)