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 
12 namespace 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
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.80.0 (Feb 21, 23:30, 2024)