FastJet 3.0.2
|
00001 //STARTHEADER 00002 // $Id: IsBase.hh 2622 2011-10-05 22:13:23Z soyez $ 00003 // 00004 // Copyright (c) 2005-2011, Matteo Cacciari, Gavin P. Salam and Gregory Soyez 00005 // 00006 //---------------------------------------------------------------------- 00007 // This file is part of FastJet. 00008 // 00009 // FastJet is free software; you can redistribute it and/or modify 00010 // it under the terms of the GNU General Public License as published by 00011 // the Free Software Foundation; either version 2 of the License, or 00012 // (at your option) any later version. 00013 // 00014 // The algorithms that underlie FastJet have required considerable 00015 // development and are described in hep-ph/0512210. If you use 00016 // FastJet as part of work towards a scientific publication, please 00017 // include a citation to the FastJet paper. 00018 // 00019 // FastJet is distributed in the hope that it will be useful, 00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 // GNU General Public License for more details. 00023 // 00024 // You should have received a copy of the GNU General Public License 00025 // along with FastJet. If not, see <http://www.gnu.org/licenses/>. 00026 //---------------------------------------------------------------------- 00027 //ENDHEADER 00028 00029 #ifndef __FASTJET_INTERNAL_IS_BASE_HH__ 00030 #define __FASTJET_INTERNAL_IS_BASE_HH__ 00031 00032 #include "fastjet/internal/numconsts.hh" 00033 00034 FASTJET_BEGIN_NAMESPACE 00035 00036 //--------------------------------------------------- 00037 // define a true and a false 'type' 00038 // Note: 00039 // we could actually template the type and recover 00040 // the TR1 integral_constant type. This also 00041 // includes adding a typedef for the type and a 00042 // typedef for the struct in the struct below 00043 // 00044 // This is going to be helpful to "split" a given 00045 // call into 2 options based on a type constraint 00046 // at compilation-time (rather than doing an "if" 00047 // which would only be resolved at runtime and could 00048 // thus resutl in compilation errors. 00049 //--------------------------------------------------- 00050 00051 /// \if internal_doc 00052 /// \class integral_type 00053 /// a generic construct that promotes a generic value of a generic type 00054 /// as a type 00055 /// 00056 /// this has 2 template parameters: T, the considered type, and _t, a 00057 /// value of type T 00058 /// This object is a basic construct in type traits 00059 /// \endif 00060 template<typename T, T _t> 00061 struct integral_type{ 00062 static const T value = _t; ///< the value (only member carrying info) 00063 typedef T value_type; ///< a typedef for the type T 00064 typedef integral_type<T,_t> type; ///< a typedef for the whole structure 00065 }; 00066 00067 // definition of the static member in integral_type 00068 template<typename T, T _t> 00069 const T integral_type<T, _t>::value; 00070 00071 // shortcuts 00072 typedef integral_type<bool, true> true_type; ///< the bool 'true' value promoted to a type 00073 typedef integral_type<bool, false> false_type; ///< the bool 'false' value promoted to a type 00074 00075 00076 //--------------------------------------------------- 00077 // define a yes and a no type (based on their size) 00078 //--------------------------------------------------- 00079 typedef char (&__yes_type)[1]; //< the yes type 00080 typedef char (&__no_type) [2]; //< the no type 00081 00082 00083 //--------------------------------------------------- 00084 // Now deal with inheritance checks 00085 // 00086 // We want to provide a IsBaseAndDerived<B,D> type 00087 // trait that contains a value that is true if D 00088 // is derived from B and false otherwise. 00089 // 00090 // For an explanation of how the code below works, 00091 // have a look at 00092 // http://groups.google.com/group/comp.lang.c++.moderated/msg/dd6c4e4d5160bd83 00093 // and the links therein 00094 // 00095 // WARNING: according to 'boost', this may have some 00096 // issues with MSVC7.1. See their code for a description 00097 // of the workaround used below 00098 //--------------------------------------------------- 00099 00100 /// \if internal_doc 00101 /// \class __inheritance_helper 00102 /// helper for IsBasedAndDerived<B,D> 00103 /// \endif 00104 template<typename B, typename D> 00105 struct __inheritance_helper{ 00106 #if !((_MSC_VER !=0 ) && (_MSC_VER == 1310)) // MSVC 7.1 00107 template <typename T> 00108 static __yes_type check_sig(D const volatile *, T); 00109 #else 00110 static __yes_type check_sig(D const volatile *, long); 00111 #endif 00112 static __no_type check_sig(B const volatile *, int); 00113 }; 00114 00115 /// \if internal_doc 00116 /// \class IsBaseAndDerived 00117 /// check if the second template argument is derived from the first one 00118 /// 00119 /// this class has 2 template dependencies: B and D. It contains a 00120 /// static boolean value that will be true if D is derived from B and 00121 /// false otherwise. 00122 /// 00123 /// Note: This construct may have a problem with MSVC7.1. See the 00124 /// boost implementation for a description and workaround 00125 /// \endif 00126 template<typename B, typename D> 00127 struct IsBaseAndDerived{ 00128 #if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000)) 00129 #pragma warning(push) 00130 #pragma warning(disable:6334) 00131 #endif 00132 00133 00134 /// \if internal_doc 00135 /// a helper structure that will pick between a casting to B*const 00136 /// or D. 00137 /// 00138 /// precisely how this structure works involves advanced C++ 00139 /// conversion rules 00140 /// \endif 00141 struct Host{ 00142 #if !((_MSC_VER !=0 ) && (_MSC_VER == 1310)) 00143 operator B const volatile *() const; 00144 #else 00145 operator B const volatile * const&() const; 00146 #endif 00147 operator D const volatile *(); 00148 }; 00149 00150 /// the boolean value being true if D is derived from B 00151 static const bool value = ((sizeof(B)!=0) && 00152 (sizeof(D)!=0) && 00153 (sizeof(__inheritance_helper<B,D>::check_sig(Host(), 0)) == sizeof(__yes_type))); 00154 00155 #if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000)) 00156 #pragma warning(pop) 00157 #endif 00158 }; 00159 00160 00161 /// a little helper that returns a pointer to d of type B* if D is 00162 /// derived from B and NULL otherwise 00163 template<class B, class D> 00164 B* cast_if_derived(D* d){ 00165 return IsBaseAndDerived<B,D>::value ? (B*)(d) : NULL; 00166 } 00167 00168 00169 FASTJET_END_NAMESPACE 00170 00171 00172 #endif // __IS_BASE_OF_HH__