Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 09:06:55

0001 // -*- C++ -*-
0002 #ifndef RIVET_TypeTraits_HH
0003 #define RIVET_TypeTraits_HH
0004 
0005 #include <type_traits>
0006 #include <iterator>
0007 
0008 namespace Rivet {
0009 
0010 
0011   /// Mechanisms to allow references and pointers to templated types
0012   /// to be distinguished from one another (since C++ doesn't allow
0013   /// partial template specialisation for functions.
0014   ///
0015   /// Traits methods use specialisation of class/struct templates, and
0016   /// some trickery with typedefs and static const integral types (or
0017   /// enums) to implement partial function specialisation as a work-around.
0018 
0019   /// @cond INTERNAL
0020 
0021   struct RefType { };
0022 
0023   struct PtrType { };
0024 
0025   template <typename T>
0026   struct TypeTraits;
0027 
0028   template <typename U>
0029   struct TypeTraits<const U&> {
0030     using ArgType = RefType;
0031   };
0032 
0033   template <typename U>
0034   struct TypeTraits<const U*> {
0035     using ArgType = PtrType;
0036   };
0037 
0038   template<typename T>
0039   struct TypeIdentity { using type = T; };
0040 
0041 
0042   /// Conditional to return the signed integer type, otherwise same type
0043   template<typename T>
0044   using sign_if_integral = std::conditional_t<(std::is_integral_v<T> && !std::is_same_v<T,bool>),
0045                                         std::make_signed<T>, TypeIdentity<T>>;
0046   //
0047   template<typename T>
0048   using sign_if_integral_t = typename sign_if_integral<T>::type;
0049 
0050   /// Conditional to return true if all input parameters are unsgined
0051   template<typename... Args>
0052   using all_unsigned = std::conjunction<std::is_unsigned<Args>...>;
0053 
0054   /// Conditional to return signed common type if input types are mixed signed/unsigned
0055   template<typename... Args>
0056   using signed_if_mixed_t = std::conditional_t<all_unsigned<Args...>::value,
0057                                                std::common_type_t<Args...>,
0058                                                std::common_type_t<sign_if_integral_t<Args>...>>;
0059 
0060 
0061   /// SFINAE definition of dereferenceability trait, cf. Boost has_dereference
0062   template <typename T, typename=void>
0063   struct Derefable : std::false_type {};
0064   //
0065   template <typename T>
0066   struct Derefable<T, std::void_t< decltype(*std::declval<T>())> > : std::true_type {};
0067 
0068 
0069   /// SFINAE struct to check for iterator concept
0070   ///
0071   /// @note Also works for C-style arrays.
0072   template<typename T, typename = void>
0073   struct Iterable : std::false_type { };
0074   //
0075   template<typename T>
0076   struct Iterable<T, std::void_t<std::decay_t<decltype(std::begin(std::declval<const T&>()))>,
0077                                  std::decay_t<decltype(std::end(std::declval<const T&>()))>>>  : std::true_type { };
0078 
0079   template<typename T>
0080   inline constexpr bool is_iterable_v = Iterable<T>::value;
0081 
0082   //template<typename... T>
0083   //inline constexpr bool isIterable = std::conjunction<Iterable<T>...>::value;
0084   template<typename T>
0085   using isIterable = std::enable_if_t<Iterable<T>::value>;
0086 
0087 
0088   // SFINAE struct to check for const_iterator concept
0089   template<typename T, typename = void>
0090   struct CIterable : std::false_type { };
0091 
0092   template<typename T>
0093   struct CIterable<T, std::void_t<decltype(std::declval<typename std::decay_t<T>::const_iterator>())>> : std::true_type { };
0094 
0095   template<typename T>
0096   inline constexpr bool is_citerable_v = CIterable<T>::value;
0097 
0098   //template<typename... T>
0099   //inline constexpr bool isCIterable = std::conjunction<CIterable<T>...>::value;
0100   template<typename... Args>
0101   using isCIterable = std::enable_if_t<(CIterable<Args>::value && ...)>;
0102 
0103   // SFINAE struct to check for cstr
0104   template<typename T>
0105   struct isCString : std::false_type { };
0106 
0107   template<>
0108   struct isCString<char[]> : std::true_type { };
0109 
0110   template<size_t N>
0111   struct isCString<char[N]> : std::true_type { };
0112 
0113   template <typename T>
0114   inline constexpr bool is_cstring_v = isCString<T>::value;
0115 
0116 
0117   /// SFINAE check if T has a binning() method
0118   template<typename T, typename = void>
0119   struct hasBinning : std::false_type { };
0120   //
0121   template<typename T>
0122   struct hasBinning<T, std::void_t<decltype(std::declval<T>().binning())>> : std::true_type { };
0123 
0124 
0125   /// SFINAE check if T is a YODA Fillable
0126   template<typename T, typename = void>
0127   struct isFillable : std::false_type { };
0128   //
0129   template<typename T>
0130   struct isFillable<T, std::void_t<decltype(typename T::FillType{})>> : std::true_type { };
0131 
0132 
0133   // SFINAE struct to check if U can be used as an argument of T
0134   template<typename T, typename U, typename = void>
0135   struct isArgumentOf : std::false_type { };
0136   //
0137   template<typename T, typename U>
0138   struct isArgumentOf<T, U, std::void_t<decltype(T(std::declval<U>()))>>
0139                   : std::true_type { };
0140 
0141   /// Check if all elements in parameter pack Us can be used as an argument of T
0142   template <typename T, typename... Us>
0143   using allArgumentsOf = typename std::conjunction<isArgumentOf<T, Us>...>;
0144 
0145   /// SFINAE check if T has XYZ methods
0146   template <typename T, typename=void>
0147   struct HasXYZ : std::false_type {};
0148   template <typename T>
0149   struct HasXYZ<T, std::void_t< decltype(std::declval<T>().x() + std::declval<T>().y() +
0150                                          std::declval<T>().z())> > : std::true_type {};
0151 
0152 
0153   /// SFINAE check if T has XYZT methods
0154   template <typename T, typename=void>
0155   struct HasXYZT : std::false_type {};
0156   template <typename T>
0157   struct HasXYZT<T, std::void_t< decltype(std::declval<T>().x() +  std::declval<T>().y() +
0158                                           std::declval<T>().z() +  std::declval<T>().t())> > : std::true_type {};
0159 
0160 
0161   /// @endcond
0162 
0163 }
0164 
0165 #endif