Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 10:49:28

0001 #ifndef DataFormats_Common_WrapperDetail_h
0002 #define DataFormats_Common_WrapperDetail_h
0003 
0004 /*----------------------------------------------------------------------
0005 
0006 WrapperDetail: Metafunction support for compile-time selection of code.
0007 
0008 ----------------------------------------------------------------------*/
0009 
0010 #include <memory>
0011 #include <typeinfo>
0012 #include <type_traits>
0013 #include <vector>
0014 
0015 namespace edm {
0016 
0017   //Need to specialize the case of std::vector<edm::Ptr<T>>
0018   template <typename T>
0019   class Ptr;
0020 
0021   namespace detail {
0022     using no_tag = std::false_type;  // type indicating FALSE
0023     using yes_tag = std::true_type;  // type indicating TRUE
0024 
0025     // valueTypeInfo_() will return typeid(T::value_type) if T::value_type is declared and typeid(void) otherwise.
0026     // Definitions for the following struct and function templates are not needed; we only require the declarations.
0027     template <typename T>
0028     static yes_tag has_value_type(typename T::value_type*);
0029     template <typename T>
0030     static no_tag has_value_type(...);
0031 
0032     template <typename T>
0033     struct has_typedef_value_type {
0034       static constexpr bool value = std::is_same<decltype(has_value_type<T>(nullptr)), yes_tag>::value;
0035     };
0036     template <typename T, bool = has_typedef_value_type<T>::value>
0037     struct getValueType;
0038     template <typename T>
0039     struct getValueType<T, true> {
0040       std::type_info const& operator()() { return typeid(typename T::value_type); }
0041     };
0042     template <typename T>
0043     struct getValueType<T, false> {
0044       std::type_info const& operator()() { return typeid(void); }
0045     };
0046 
0047     // memberTypeInfo_() will return typeid(T::member_type) if T::member_type is declared and typeid(void) otherwise.
0048     // Definitions for the following struct and function templates are not needed; we only require the declarations.
0049     template <typename T>
0050     static yes_tag has_member_type(typename T::member_type*);
0051     template <typename T>
0052     static no_tag has_member_type(...);
0053 
0054     template <typename T>
0055     struct has_typedef_member_type {
0056       static constexpr bool value = std::is_same<decltype(has_member_type<T>(nullptr)), yes_tag>::value;
0057     };
0058     template <typename T, bool = has_typedef_member_type<T>::value>
0059     struct getMemberType;
0060     template <typename T>
0061     struct getMemberType<T, true> {
0062       std::type_info const& operator()() { return typeid(typename T::member_type); }
0063     };
0064     template <typename T>
0065     struct getMemberType<T, false> {
0066       std::type_info const& operator()() { return typeid(void); }
0067     };
0068 
0069     template <typename T>
0070     struct has_typedef_member_type<std::vector<edm::Ptr<T> > > {
0071       static constexpr bool value = true;
0072     };
0073 
0074     template <typename T>
0075     struct getMemberType<std::vector<edm::Ptr<T> >, true> {
0076       std::type_info const& operator()() { return typeid(T); }
0077     };
0078 
0079     template <typename T, typename Deleter>
0080     struct has_typedef_member_type<std::vector<std::unique_ptr<T, Deleter> > > {
0081       static constexpr bool value = true;
0082     };
0083 
0084     template <typename T, typename Deleter>
0085     struct getMemberType<std::vector<std::unique_ptr<T, Deleter> >, true> {
0086       std::type_info const& operator()() { return typeid(T); }
0087     };
0088 
0089     // bool isMergeable_() will return true if T::mergeProduct(T const&) is declared and false otherwise
0090     // bool mergeProduct_(WrapperBase const*) will merge products if T::mergeProduct(T const&) is defined
0091     // Definitions for the following struct and function templates are not needed; we only require the declarations.
0092     template <typename T, bool (T::*)(T const&)>
0093     struct mergeProduct_function;
0094     template <typename T>
0095     static yes_tag has_mergeProduct(mergeProduct_function<T, &T::mergeProduct>* dummy);
0096     template <typename T>
0097     static no_tag has_mergeProduct(...);
0098 
0099     template <typename T>
0100     struct has_mergeProduct_function {
0101       static constexpr bool value = std::is_same<decltype(has_mergeProduct<T>(nullptr)), yes_tag>::value;
0102     };
0103 
0104     template <typename T, bool = has_mergeProduct_function<T>::value>
0105     struct getHasMergeFunction;
0106     template <typename T>
0107     struct getHasMergeFunction<T, true> {
0108       bool operator()() { return true; }
0109     };
0110     template <typename T>
0111     struct getHasMergeFunction<T, false> {
0112       bool operator()() { return false; }
0113     };
0114     template <typename T, bool = has_mergeProduct_function<T>::value>
0115     struct doMergeProduct;
0116     template <typename T>
0117     struct doMergeProduct<T, true> {
0118       bool operator()(T& thisProduct, T const& newProduct) { return thisProduct.mergeProduct(newProduct); }
0119     };
0120     template <typename T>
0121     struct doMergeProduct<T, false> {
0122       bool operator()(T& thisProduct, T const& newProduct) {
0123         return true;  // Should never be called
0124       }
0125     };
0126 
0127     // bool hasIsProductEqual_() will return true if T::isProductEqual(T const&) const is declared and false otherwise
0128     // bool isProductEqual _(WrapperBase const*) will call T::isProductEqual(T const&) if it is defined
0129     // Definitions for the following struct and function templates are not needed; we only require the declarations.
0130     template <typename T, bool (T::*)(T const&) const>
0131     struct isProductEqual_function;
0132     template <typename T>
0133     static yes_tag has_isProductEqual(isProductEqual_function<T, &T::isProductEqual>* dummy);
0134     template <typename T>
0135     static no_tag has_isProductEqual(...);
0136 
0137     template <typename T>
0138     struct has_isProductEqual_function {
0139       static constexpr bool value = std::is_same<decltype(has_isProductEqual<T>(nullptr)), yes_tag>::value;
0140     };
0141 
0142     template <typename T, bool = has_isProductEqual_function<T>::value>
0143     struct getHasIsProductEqual;
0144     template <typename T>
0145     struct getHasIsProductEqual<T, true> {
0146       bool operator()() { return true; }
0147     };
0148     template <typename T>
0149     struct getHasIsProductEqual<T, false> {
0150       bool operator()() { return false; }
0151     };
0152     template <typename T, bool = has_isProductEqual_function<T>::value>
0153     struct doIsProductEqual;
0154     template <typename T>
0155     struct doIsProductEqual<T, true> {
0156       bool operator()(T const& thisProduct, T const& newProduct) { return thisProduct.isProductEqual(newProduct); }
0157     };
0158     template <typename T>
0159     struct doIsProductEqual<T, false> {
0160       bool operator()(T const& thisProduct, T const& newProduct) {
0161         return true;  // Should never be called
0162       }
0163     };
0164 
0165     // bool hasSwap_() will return true if T::swap(T&) is declared and false otherwise
0166     // void swapProduct_() will call T::swap(T&) if it is defined otherwise it does nothing
0167     // Definitions for the following struct and function templates are not needed; we only require the declarations.
0168     template <typename T, void (T::*)(T&)>
0169     struct swap_function;
0170     template <typename T>
0171     static yes_tag has_swap(swap_function<T, &T::swap>* dummy);
0172     template <typename T>
0173     static no_tag has_swap(...);
0174 
0175     template <typename T>
0176     struct has_swap_function {
0177       static constexpr bool value = std::is_same<decltype(has_swap<T>(nullptr)), yes_tag>::value;
0178     };
0179 
0180     template <typename T, bool = has_swap_function<T>::value>
0181     struct getHasSwapFunction;
0182     template <typename T>
0183     struct getHasSwapFunction<T, true> {
0184       bool operator()() { return true; }
0185     };
0186     template <typename T>
0187     struct getHasSwapFunction<T, false> {
0188       bool operator()() { return false; }
0189     };
0190     template <typename T, bool = has_swap_function<T>::value>
0191     struct doSwapProduct;
0192     template <typename T>
0193     struct doSwapProduct<T, true> {
0194       void operator()(T& thisProduct, T& newProduct) { thisProduct.swap(newProduct); }
0195     };
0196     template <typename T>
0197     struct doSwapProduct<T, false> {
0198       void operator()(T&, T&) {
0199         return;  // Should never be called
0200       }
0201     };
0202   }  // namespace detail
0203 }  // namespace edm
0204 #endif