SUNphi  1.0
TypeTraits.hpp
Go to the documentation of this file.
1 #ifndef _TYPETRAITS_HPP
2 #define _TYPETRAITS_HPP
3 
4 /// \file TypeTraits.hpp
5 ///
6 /// \brief Defines convenient adaptation of the std type_traits
7 /// library, and extensions useful for the expression handling.
8 
9 #ifdef HAVE_CONFIG_H
10  #include <config.hpp>
11 #endif
12 
13 #include <type_traits>
14 #include <utility>
15 
16 #include <metaprogramming/SwallowSemicolon.hpp>
17 
18 namespace SUNphi
19 {
20  /// A bool constant type holding value "true"
21  ///
22  /// Useful to create SFINAE tests
23  using TrueType=
24  std::true_type;
25 
26  /// A bool constant type holding value "false"
27  ///
28  /// Useful to create SFINAE tests
29  using FalseType=
30  std::false_type;
31 
32  /////////////////////////////////////////////////////////////////
33 
34  /// Empty token to be used in macro expecting qualifier
35 #define NON_CONST_QUALIF
36 
37  /// Token to be used in macro indicating "const" keyword
38 #define CONST_QUALIF
39  const
40 
41  /// Empty token to be used in macro expecting the kind of reference
42 #define NON_REF
43 
44  /// Token to be used in macro indicating "l-value" reference
45 #define LVALUE_REF
46  &
47 
48  /// Token to be used in macro indicating "r-value" reference
49 #define RVALUE_REF
50  &&
51 
52  /////////////////////////////////////////////////////////////////
53 
54  /// Delete the copy-constructor
55 #define FORBID_CONSTRUCT_BY_COPY(CLASS)
56  CLASS(const CLASS&)=
57  delete
58 
59  /////////////////////////////////////////////////////////////////////
60 
61  /// Defines type T (default to void) if parameter B is true
62  ///
63  /// Useful to enable or disable SFINAE specialization.
64  /// Generic (false) case
65  template <bool B, // Boolean constant deciding whether the type is enabled
66  typename T> // Type to be enabled
67  struct _EnableIf
68  {
69  };
70 
71  /// Defines type T (default to void) if parameter B is true
72  ///
73  /// Useful to enable or disable SFINAE specialization.
74  /// True case
75  template <typename T> // Type to be enabled
76  struct _EnableIf<true,T>
77  {
78  /// Type enabled
79  typedef T type;
80  };
81 
82  /// Defines type T (default to void) if parameter B is true
83  ///
84  /// Gives visibility to the internal implementation
85  template <bool B, // Boolean constant deciding whether the type is enabled
86  typename T=void> // Type to be enabled
87  using EnableIf=
88  typename _EnableIf<B,T>::type;
89 
90  /// Defines \c void if parameter B is true
91  ///
92  /// Explicit specialization of \c EnableIf for \c T=void .
93  template <bool B>
94  using VoidIf=
95  EnableIf<B>;
96 
97  /// Defines type T if parameter B is true
98  ///
99  /// Explicit specialization of \c EnableIf forcing an explicit type.
100  template <bool B, // Boolean constant deciding whether the type is enabled
101  typename T> // Type to be enabled
102  using TypeIf=
103  EnableIf<B,T>;
104 
105  /////////////////////////////////////////////////////////////////
106 
107  /// Checks if a type is a class
108  template <typename T> // Type to check
109  [[ maybe_unused ]]
110  static constexpr bool isClass=
111  std::is_class_v<T>;
112 
113  /// Checks if a type can be cast into another one
114  template <typename From, // Source type
115  typename To> // Destination type
116  [[ maybe_unused ]]
117  static constexpr bool canBeConverted=
118  std::is_convertible_v<From,To>;
119 
120  /// Checks if an object can be trivially copied
121  template <typename T> // Type to check
122  [[ maybe_unused ]]
123  static constexpr bool isTriviallyCopyable=
124  std::is_trivially_copyable_v<T>;
125 
126  /////////////////////////////////////////////////////////////////
127 
128  /// Checks if two types are the same
129  ///
130  /// Default (false) case
131  template <typename T1, // First type to be checked
132  typename T2> // Second type to be checked
133  [[ maybe_unused ]]
134  static constexpr bool isSame=
135  false;
136 
137  /// Checks if two types are the same
138  ///
139  /// True case
140  template <typename T> // Specialize with a unique type
141  static constexpr bool isSame<T,T> =
142  true;
143 
144  /////////////////////////////////////////////////////////////////
145 
146  /// Returns true if all types Ts are the same
147  ///
148  /// Internal implementation
149  template <typename T=void,
150  typename...Tail>
151  constexpr bool _areSame()
152  {
153  if constexpr(sizeof...(Tail)==0)
154  return true;
155  else
156  return (isSame<T,Tail> && ...);
157  }
158 
159  /// Returns true if all Ts are the same type
160  ///
161  /// Gives visibility to internal representation
162  template <typename...Ts>
163  [[ maybe_unused ]]
164  constexpr bool areSame=
165  _areSame<Ts...>();
166 
167  /// Assert if types are not the same
168 #define STATIC_ASSERT_ARE_SAME(...)
169  static_assert(areSame<__VA_ARGS__>,"Error, types are not the same")
170 
171  /// Forces a set of types to be the same
172  template <class...Args>
174  {
175  STATIC_ASSERT_ARE_SAME(Args...);
176  };
177 
178  /////////////////////////////////////////////////////////////////////
179 
180  /// Provides type T if B is true, or F if is false
181  ///
182  /// Forward declaration of internal implementation
183  template <bool B,
184  typename T,
185  typename F>
186  struct _Conditional;
187 
188  /// Provides type T if B is true, or F if is false
189  ///
190  /// True case of internal implementation
191  template <typename T,
192  typename F>
193  struct _Conditional<true,T,F>
194  {
195  /// Internal type (T)
196  typedef T type;
197  };
198 
199  /// Provides type T if B is true, or F if is false
200  ///
201  /// False case of internal implementation
202  template <typename T,
203  typename F>
204  struct _Conditional<false,T,F>
205  {
206  /// Internal type (F)
207  typedef F type;
208  };
209 
210  /// Provides type T if B is true, or F if is false
211  ///
212  /// Wraps the internal implementation
213  template <bool B, // Condition enabling one or the other type
214  typename T, // T Type enabled if true
215  typename F> // F Type enabled if false
216  using Conditional=
217  typename _Conditional<B,T,F>::type;
218 
219  /////////////////////////////////////////////////////////////////
220 
221  /// Returns the type T without any reference
222  template <typename T>
223  using RemRef=
224  typename std::remove_reference<T>::type;
225 
226  /// Check if the type is lvalue reference
227  template <typename T>
228  [[ maybe_unused ]]
229  constexpr bool isLvalue=
230  std::is_lvalue_reference<T>::value;
231 
232  /// Check if the type is rvalue reference
233  template <typename T>
234  [[ maybe_unused ]]
235  constexpr bool isRvalue=
236  std::is_rvalue_reference<T>::value;
237 
238  /// Returns reference of plain type depending on condition
239  template <bool B, // Condition
240  typename _T, // Type
241  typename T=RemRef<_T>> // Remove reference from type
242  using RefIf=
243  Conditional<B,T&,T>;
244 
245  /////////////////////////////////////////////////////////////////
246 
247  /// Returns the type T without any constant volatile qualification
248  template <typename T>
249  using RemoveCV=
250  typename std::remove_cv<T>::type;
251 
252  /// Returns whether T is const or not
253  ///
254  /// Warning!!! This is not the same than asking \c std::is_const
255  template <typename _T, // Asked type
256  typename T=RemRef<_T>> // Type without ref
257  [[ maybe_unused ]]
258  constexpr bool isConst=
259  not isSame<RemoveCV<T>,T>;
260 
261  /// Returns const or non const T depending on condition
262  template <bool B, // Condition
263  typename _T, // Type
264  typename T=RemoveCV<_T>> // Remove const from type
265  using ConstIf=
266  Conditional<B,const T,T>;
267 
268  /// Returns the type T without any reference or qualifier
269  template <typename T>
270  using Unqualified=
271  RemoveCV<RemRef<T>>;
272 
273  /////////////////////////////////////////////////////////////////
274 
275  /// Checks if it is pointer
276  template <typename T>
277  [[ maybe_unused ]]
278  static constexpr bool isPointer=
279  std::is_pointer_v<T>;
280 
281  /////////////////////////////////////////////////////////////////
282 
283  /// Returns the type T without any reference or qualifier or pointer
284  ///
285  /// Helper to the actual implementation
286  template <typename T>
287  constexpr auto fundamentalHelper()
288  {
289  if constexpr(isConst<T>)
290  return
291  fundamentalHelper<RemoveCV<T>>();
292  else
293  if constexpr(isPointer<T>)
294  return
295  fundamentalHelper<std::remove_pointer_t<T>>();
296  else
297  return
298  std::decay_t<T>{};
299  }
300 
301  /// Returns the type T without any reference or qualifier or pointer
302  template <typename T>
303  using Fundamental=
304  decltype(fundamentalHelper<T>());
305 
306  /////////////////////////////////////////////////////////////////////
307 
308  /// Identifies whether Base is a base class of Derived
309  template <typename Base, // The type that can be base
310  typename Derived> // The type where Base is searched
311  [[ maybe_unused]]
312  constexpr bool isBaseOf=
313  std::is_base_of<Base,RemRef<Derived>>::value;
314 
315  /////////////////////////////////////////////////////////////////
316 
317  /// Returns whether the passed argument is a function
318  template <typename F>
319  [[ maybe_unused ]]
320  constexpr bool isFunction=
321  std::is_function_v<F>;
322 
323  /// Returns a pointer-version of F
324  template <typename F>
325  using AddPointer=
326  std::add_pointer_t<F>;
327 
328  /// Returns F or F* if F is not a function
329  template <typename F>
330  using AddPointerIfFunction=
331  Conditional<isFunction<F>,
332  AddPointer<F>,
333  F>;
334 
335  /////////////////////////////////////////////////////////////////
336 
337  /// Remove \c const qualifier from anything
338  ///
339  /// \todo Check that the "dangling reference forbidding" below,
340  /// currently not working, is not actually necessary
341  template <typename T>
342  constexpr T& asMutable(const T& v) noexcept
343  {
344  return const_cast<T&>(v);
345  }
346 
347  // /// Forbids a dangling reference
348  // template <typename T>
349  // void asMutable(const T&&)=delete;
350 
351  /// Call a const method removing any const qualifier
352 #define CALL_CLASS_CONST_METHOD_REMOVING_CONST(...)
353  asMutable(std::as_const(*this).__VA_ARGS__)
354 
355  /// Provides also a non-const version of the method \c NAME
356  ///
357  /// See
358  /// https://stackoverflow.com/questions/123758/how-do-i-remove-code-duplication-between-similar-const-and-non-const-member-func
359  /// A const method NAME must be already present Example
360  ///
361  /// \code
362  // class ciccio
363  /// {
364  /// double e{0};
365  ///
366  /// public:
367  ///
368  /// const double& get() const
369  /// {
370  /// return e;
371  /// }
372  ///
373  /// PROVIDE_ALSO_NON_CONST_METHOD(get);
374  /// };
375  /// \endcode
376 #define PROVIDE_ALSO_NON_CONST_METHOD(NAME)
377  /*! Overload the \c NAME const method passing all args */
378  template <typename...Ts> /* Type of all arguments */
379  DECLAUTO NAME(Ts&&...ts) /*!< Arguments */
380  {
381  return
382  CALL_CLASS_CONST_METHOD_REMOVING_CONST(NAME(forw<Ts>(ts)...));
383  }
384 
385  /////////////////////////////////////////////////////////////////
386 
387  /// Static assert if DERIVED does not derive from BASE
388 #define STATIC_ASSERT_IS_BASE_OF(BASE,DERIVED)
389  static_assert(isBaseOf<BASE,DERIVED>,"Error, type not derived from what expected")
390 
391  /// Static assert if DERIVED does derive from BASE
392 #define STATIC_ASSERT_IS_NOT_BASE_OF(BASE,DERIVED)
393  static_assert(not isBaseOf<BASE,DERIVED>,"Error, type derived from what not expected")
394 
395  /// Forces type Derived to be derived from Base
396  template <typename Base,
397  typename Derived>
398  struct ConstrainIsBaseOf
399  {
400  STATIC_ASSERT_IS_BASE_OF(Base,Derived);
401 
402  /// Type checked
403  using type=
404  Derived;
405  };
406 
407  /// Forces type Derived not to be derived from Base
408  template <typename Base,
409  typename Derived>
411  {
412  STATIC_ASSERT_IS_NOT_BASE_OF(Base,Derived);
413 
414  /// Type checked
415  using type=
416  Derived;
417  };
418 
419  /////////////////////////////////////////////////////////////////
420 
421  /// Static assert if not passing exactly N types
422 #define STATIC_ASSERT_ARE_N_TYPES(N,UNEXP_PARPACK)
423  static_assert(N==sizeof...(UNEXP_PARPACK),"Error, expecting a different number of types")
424 
425  /// Forces types to be in the given number
426  template <int N, // Number of types expected
427  typename...Args> // Types counted
429  {
431  };
432 
433  //////////////////////////////////////////////////////////////////////
434 
435  /// Identifies whether a type is a floating-point
436  template <typename T>
437  [[ maybe_unused ]]
438  constexpr bool isFloatingPoint=std::is_floating_point<T>::value;
439 
440  /// Static assert if the type T is not a floating-point
441 #define STATIC_ASSERT_IS_FLOATING_POINT(T)
442  static_assert(isFloatingPoint<T>,"Error, type is not a floating point")
443 
444  /// Forces the type to be a floating-point
445  template <typename T>
447  {
449  };
450 
451  //////////////////////////////////////////////////////////////////////
452 
453  /// Identifies whether a type is an integer-like
454  template <typename T>
455  [[ maybe_unused ]]
456  constexpr bool isIntegral=std::is_integral<T>::value;
457 
458  /// Static assert if the type T is not an integer-like
459 #define STATIC_ASSERT_IS_INTEGRAL(T)
460  static_assert(isIntegral<T>,"Error, type is not an integral")
461 
462  /// Forces the type to be integer-like
463  template <typename T>
465  {
467  };
468 
469  /////////////////////////////////////////////////////////////////
470 
471  /// Identifies whether a set of types are a integer-like
472  template <typename Head=int,
473  typename...Tail>
474  [[ maybe_unused ]]
475  constexpr bool areIntegrals=
476  areIntegrals<Head> and areIntegrals<Tail...>;
477 
478  /// Identifies whether a single types is integer-like
479  template <typename T>
480  constexpr bool areIntegrals<T> =
481  isIntegral<T>;
482 
483  /// Static assert if the types T are not an integer-like
484 #define STATIC_ASSERT_ARE_INTEGRALS(...)
485  static_assert(areIntegrals<__VA_ARGS__>,"Error, types are not all an integral")
486 
487  /// Forces the type to be integer-like
488  template <typename...Args>
490  {
492  };
493 
494  /////////////////////////////////////////////////////////////////
495 
496  /// Provides an EnableIf with the given name for a certain condition
497  ///
498  /// Must be declared with deduced type to void template parameters
499  /// that cannot be deduced
500 #define PROVIDE_ENABLE_IF_FOR(TYPE,
501  ...)
502  /*! Provides the class itself if T satisfies the condition */
503  template <typename T,
504  typename Ret=void>
505  using EnableIfIs ## TYPE=
506  EnableIf<__VA_ARGS__,Ret>
507 
508  /// Provides an EnableIf with the given name if isTYPE exists
509 #define PROVIDE_ENABLE_IF_FOR_IS_TYPE(TYPE)
510  /*! Provides the class itself if T is of the given type */
511  PROVIDE_ENABLE_IF_FOR(TYPE,is ## TYPE<T>)
512 
513  /// Provides an EnableIf with the given type
514 #define PROVIDE_ENABLE_IF_FOR_TYPE(TYPE)
515  /*! Provides the class itself if T is of the given type */
516  PROVIDE_ENABLE_IF_FOR(TYPE,isSame<T,TYPE>)
517 
518  /////////////////////////////////////////////////////////////////
519 
520  /// Defines a "Base" identifier and checks for it
521  ///
522  /// Given a TYPE, defines another empty type prefixing its name with
523  /// "Base", and defines a check IsTYPE to probe wheter a certain
524  /// type inherit from TYPE. All extra arguments can be used to
525  /// specify inheritance from other classes
526 #define DEFINE_BASE_TYPE(TYPE,...)
527  struct Base ## TYPE __VA_ARGS__ {};
528 
529  /*! Expression which is true if T inherits from \c Base ## TYPE */
530  template <typename T>
531  [[ maybe_unused ]]
532  constexpr bool is ## TYPE=
533  isBaseOf<Base ## TYPE,T>;
534 
536 
537  /*! Class forcing T to inherits from \c Base ## TYPE */
538  template <typename T>
539  using ConstrainIs ## TYPE=
540  ConstrainIsBaseOf<Base ## TYPE,T>;
541 
542  /*! Class forcing T not to inherits from \c Base ## TYPE */
543  template <typename T>
544  using ConstrainIsNot ## TYPE=
545  ConstrainIsNotBaseOf<Base ## TYPE,T>;
546 
547  /*! Static assert if the types do not inherit from \c Base ## TYPE */
548  template <typename...Args>
549  struct ConstrainAre ## TYPE ## s
550  {
551  static_assert((is ## TYPE<Args> && ...),
552  "Error, types are not all " #TYPE);
553  }
554 
555  /////////////////////////////////////////////////////////////////
556 
557  /// Assert type T to have member TAG
558  ///
559  /// Note that you need to have defined DEFINE_HAS_MEMBER before
560 #define STATIC_ASSERT_HAS_MEMBER(TAG,...)
561  static_assert(hasMember_ ## TAG<__VA_ARGS__>,"Type does not have member " #TAG)
562 
563  /// Define a member detecter named hasMember_TAG
564  ///
565  /// Example:
566  ///
567  /// \code
568  /// DEFINE_HAS_MEMBER(ciccio);
569  ///
570  /// struct fuffa
571  /// {
572  /// int ciccio();
573  /// };
574  ///
575  /// int main()
576  /// {
577  /// bool has=hasMember_ciccio(fuffa);
578  /// return 0;
579  /// }
580  /// \endcode
581 #define DEFINE_HAS_MEMBER(TAG)
582  /*! Detect if \c Type has member (variable or method) TAG */
583  /*! */
584  /*! Internal implementation */
585  template <typename Type>
586  struct HasMember_ ## TAG
587  {
588  /*! Internal class of size 1, used if Type has the method */
589  using Yes=char[1];
590 
591  /*! Internal class of size 2 used if Type has not the method */
592  using No=char[2];
593 
594  /*! Internal class which does implement the method TAG */
595  struct Fallback
596  {
597  /*! Member actually implemented */
598  int TAG;
599  };
600 
601  /*! This class inherits from both Type and Fallback, so it will */
602  /*! certainly have the method TAG, possibly two */
603  struct Derived :
604  public Type,
605  public Fallback
606  {
607  };
608 
609  /*! This type can be instantiated only if the U type is */
610  /*! unambiguosly understood.*/
611  template <typename U,
612  U>
613  struct Check;
614 
615  /*! Forward definition of test function, taking a pointer to the */
616  /*! type of TAG as argument, returning No. The instantiation */
617  /*! will fail if Base have two member TAG implemented, which */
618  /*! means that Type has the member */
619  template <typename U>
620  static No& test(Check<int Fallback::*,&U::TAG>*);
621 
622  /*! Forward definition of test function, taking a pointer to the */
623  /*! type of TAG as argument, returning Yes. The instantiation */
624  /*! will work when the other fails, which means that Type does */
625  /*! have the member */
626  template <typename U>
627  static Yes& test(...);
628 
629  public:
630  /*! Result of the check, comparing the size of return type of */
631  /*! test with the size of yes */
632  static constexpr bool result=
633  sizeof(test<Derived>(nullptr))==sizeof(Yes);
634  };
635 
636  /*! Intemediate function to distinguish the non-class case */
637  template <typename Type>
638  [[ maybe_unused ]]
639  constexpr bool hasMember_ ## TAG ## Helper()
640  {
641  if constexpr(isClass<Type>)
642  return
643  HasMember_ ## TAG<Type>::result;
644  else
645  return
646  false;
647  }
648 
649  /*! Detect if \c Type has member (variable or method) TAG */
650  /*! */
651  /*! Uses SFINAE to induce ambiguity in the detection of the member */
652  template <typename Type>
653  [[ maybe_unused ]]
654  constexpr bool hasMember_ ## TAG=
655  hasMember_ ## TAG ## Helper<RemRef<Type>>();
656 
657  /*! \brief Class forcing T to have a member "TAG" defined */
658  template <typename T>
659  struct ConstrainHasMember_ ## TAG
660  {
662  }
663 
664  /////////////////////////////////////////////////////////////////
665 
666  /// Check that the binary operator exists
667 #define DEFINE_BINARY_OPERATOR_IMPLEMENTATION_CHECK(CHECK_NAME,
668  STRUCT_NAME,
669  OPERATOR)
670  /*! Structure used to check if the operator is implemented */
671  template <typename S,
672  typename T>
673  struct STRUCT_NAME
674  {
675  /*! Path followed when the operator is implemented */
676  template <typename U,
677  typename V>
678  static auto test(U*)->decltype(std::declval<U>()
679  OPERATOR
680  std::declval<V>());
681 
682  /*! Default case in which the binary operation cannot be performed */
683  template <typename,
684  typename>
685  static auto test(...)->std::false_type;
686 
687  /*! Result of the check */
688  static constexpr bool res=
689  not isSame<std::false_type,decltype(test<S,T>(0))>;
690  };
691 
692  /*! Check that operator OPERATOR is implemented */
693  template <typename S,
694  typename T>
695  [[ maybe_unused ]]
696  constexpr bool CHECK_NAME=
697  STRUCT_NAME<S,T>::res
698 
700 
701  /////////////////////////////////////////////////////////////////
702 
703  /// Returns the signed version of the passed type
704  template <typename T> // Type to unsign
705  using SignedOf=
706  RefIf<isLvalue<T>,std::make_signed_t<RemRef<T>>>;
707 
708  /// Returns the unsigned version of the passed type
709  template <typename T> // Type to sign
710  using UnsignedOf=
711  RefIf<isLvalue<T>,std::make_unsigned_t<RemRef<T>>>;
712 
713  /////////////////////////////////////////////////////////////////
714 
715  /// Provides a check returning whether the class is of a given kind
716 #define DEFINE_IS_THE_TEMPLATED_CLASS(CLASS)
717  /*! Check if the class is a CLASS */
718  /*! */
719  /*! False case */
720  template <typename T>
721  constexpr bool _is ## CLASS(const T*)
722  {
723  return
724  false;
725  }
726 
727  /*! Check if the class is a CLASS */
728  /*! */
729  /*! True case */
730  template <typename...Ts>
731  constexpr bool _is ## CLASS(const CLASS<Ts...>*)
732  {
733  return
734  true;
735  }
736 
737  /*! Check if the class is a CLASS */
738  /*! */
739  /*! Calls the internal implementation */
740  template <typename T>
741  [[ maybe_unused ]]
742  constexpr bool is ## CLASS=
743  _is ## CLASS((RemRef<T>*)nullptr);
744 
746 
747  /////////////////////////////////////////////////////////////////
748 
753 
754  /// Check if the class T is vector-like
755  template <typename T>
756  [[ maybe_unused ]]
757  constexpr bool isVectorLike=
758  hasMember_begin<T> and
759  hasMember_end<T> and
760  hasMember_resize<T> and
761  hasMember_size<T>;
762 
763  namespace internal
764  {
765  /// Class returned from fall-through methods
767  {
768  };
769 
770  /// Default getter
771  template <int,
772  typename T>
773  FallTrhough get(T)
774  {
775  return {};
776  };
777  }
778 
779  /// Check if the class T can be get
780  template <typename T>
781  constexpr bool canBeGet()
782  {
783  using namespace std;
784  using namespace internal;
785 
786  return
787  not isSame<RemRef<decltype(get<0>(*static_cast<RemRef<T>*>(nullptr)))>,FallTrhough>;
788  }
789 
790  /// Check if the class T is tuple-like
791  template <typename T>
792  [[ maybe_unused ]]
793  constexpr bool isTupleLike=
794  canBeGet<T>();
795 }
796 
797 #endif
constexpr bool isIntegral
Identifies whether a type is an integer-like.
Definition: TypeTraits.hpp:456
#define STATIC_ASSERT_IS_BASE_OF(BASE, DERIVED)
Static assert if DERIVED does not derive from BASE.
Definition: TypeTraits.hpp:388
#define DEFINE_HAS_MEMBER(TAG)
Definition: TypeTraits.hpp:581
constexpr bool isRvalue
Check if the type is rvalue reference.
Definition: TypeTraits.hpp:235
constexpr bool isFloatingPoint
Identifies whether a type is a floating-point.
Definition: TypeTraits.hpp:438
#define STATIC_ASSERT_ARE_N_TYPES(N, UNEXP_PARPACK)
Static assert if not passing exactly N types.
Definition: TypeTraits.hpp:422
Forces a set of types to be the same.
Definition: TypeTraits.hpp:173
constexpr bool areIntegrals
Identifies whether a set of types are a integer-like.
Definition: TypeTraits.hpp:475
constexpr bool isLvalue
Check if the type is lvalue reference.
Definition: TypeTraits.hpp:229
#define DEFINE_BINARY_OPERATOR_IMPLEMENTATION_CHECK(CHECK_NAME,STRUCT_NAME, OPERATOR)
Check that the binary operator exists.
Definition: TypeTraits.hpp:667
constexpr bool isBaseOf
Identifies whether Base is a base class of Derived.
Definition: TypeTraits.hpp:312
#define PROVIDE_ENABLE_IF_FOR_IS_TYPE(TYPE)
Provides an EnableIf with the given name if isTYPE exists.
Definition: TypeTraits.hpp:509
#define STATIC_ASSERT_IS_INTEGRAL(T)
Static assert if the type T is not an integer-like.
Definition: TypeTraits.hpp:459
FallTrhough get(T)
Default getter.
Definition: TypeTraits.hpp:773
Forces types to be in the given number.
Definition: TypeTraits.hpp:428
#define CALL_CLASS_CONST_METHOD_REMOVING_CONST(...)
Call a const method removing any const qualifier.
Definition: TypeTraits.hpp:352
Forces the type to be a floating-point.
Definition: TypeTraits.hpp:446
#define STATIC_ASSERT_ARE_INTEGRALS(...)
Static assert if the types T are not an integer-like.
Definition: TypeTraits.hpp:484
#define STATIC_ASSERT_ARE_SAME(...)
Assert if types are not the same.
Definition: TypeTraits.hpp:168
Forces the type to be integer-like.
Definition: TypeTraits.hpp:489
constexpr bool canPrint
Definition: TypeTraits.hpp:699
#define STATIC_ASSERT_IS_NOT_BASE_OF(BASE, DERIVED)
Static assert if DERIVED does derive from BASE.
Definition: TypeTraits.hpp:392
constexpr bool isVectorLike
Check if the class T is vector-like.
Definition: TypeTraits.hpp:757
Forces the type to be integer-like.
Definition: TypeTraits.hpp:464
constexpr bool isFunction
Returns whether the passed argument is a function.
Definition: TypeTraits.hpp:320
Forces type Derived not to be derived from Base.
Definition: TypeTraits.hpp:410
#define DECLAUTO
Short name for decltype(auto)
#define STATIC_ASSERT_HAS_MEMBER(TAG,...)
Definition: TypeTraits.hpp:560
Class returned from fall-through methods.
Definition: TypeTraits.hpp:766
#define STATIC_ASSERT_IS_FLOATING_POINT(T)
Static assert if the type T is not a floating-point.
Definition: TypeTraits.hpp:441
#define PROVIDE_ENABLE_IF_FOR(TYPE,...)
Definition: TypeTraits.hpp:500