IsBase.hh

00001 #ifndef __IS_BASE_OF_HH__
00002 #define __IS_BASE_OF_HH__
00003 
00004 #include "fastjet/internal/numconsts.hh"
00005 
00006 FASTJET_BEGIN_NAMESPACE
00007 
00008 //---------------------------------------------------
00009 // define a true and a false 'type'
00010 // Note: 
00011 //  we could actually template the type and recover 
00012 //  the TR1 integral_constant type. This also 
00013 //  includes adding a typedef for the type and a
00014 //  typedef for the struct in the struct below
00015 //
00016 // This is going to be helpful to "split" a given 
00017 // call into 2 options based on a type constraint
00018 // at compilation-time (rather than doing an "if" 
00019 // which would only be resolved at runtime and could
00020 // thus resutl in compilation errors. 
00021 //---------------------------------------------------
00022 
00023 /// \if internal_doc
00024 /// \class integral type 
00025 /// a generic construct that promotes a generic value of a generic type
00026 /// as a type
00027 ///
00028 /// this has 2 template parameters: T, the considered type, and _t, a
00029 /// value of type T
00030 /// This object is a basic construct in type traits
00031 /// \endif
00032 template<typename T, T _t>
00033 struct integral_type{
00034   static const T value = _t;         ///< the value (only member carrying info)
00035   typedef T value_type;              ///< a typedef for the type T
00036   typedef integral_type<T,_t> type;  ///< a typedef for the whole structure
00037 };
00038 
00039 // definition of the static member in integral_type
00040 template<typename T, T _t>
00041 const T integral_type<T, _t>::value;
00042 
00043 // shortcuts
00044 typedef integral_type<bool, true>  true_type;  ///< the bool 'true'  value promoted to a type
00045 typedef integral_type<bool, false> false_type; ///< the bool 'false' value promoted to a type
00046 
00047 
00048 //---------------------------------------------------
00049 // define a yes and a no type (based on their size)
00050 //---------------------------------------------------
00051 typedef char (&__yes_type)[1]; //< the yes type
00052 typedef char (&__no_type) [2]; //< the no type
00053 
00054 
00055 //---------------------------------------------------
00056 // Now deal with inheritance checks
00057 //
00058 // We want to provide a IsBaseAndDerived<B,D> type 
00059 // trait that contains a value that is true if D
00060 // is derived from B and false otherwise.
00061 //
00062 // For an explanation of how the code below works, 
00063 // have a look at 
00064 //   http://groups.google.com/group/comp.lang.c++.moderated/msg/dd6c4e4d5160bd83
00065 // and the links therein
00066 //
00067 // WARNING: according to 'boost', this may have some
00068 //   issues with MSVC7.1. See their code for a description
00069 //   of the workaround used below
00070 //---------------------------------------------------
00071 
00072 /// \if internal_doc
00073 /// \class __inheritance_helper
00074 /// helper for IsBasedAndDerived<B,D>
00075 /// \endif
00076 template<typename B, typename D>
00077 struct __inheritance_helper{
00078 #if !((_MSC_VER !=0 ) && (_MSC_VER == 1310))   // MSVC 7.1
00079   template <typename T>
00080   static __yes_type check_sig(D const volatile *, T);
00081 #else
00082   static __yes_type check_sig(D const volatile *, long);
00083 #endif
00084   static __no_type  check_sig(B const volatile *, int);
00085 };
00086 
00087 /// \if internal_doc
00088 /// \class IsBaseAndDerived
00089 /// check if the second template argument is derived from the first one
00090 /// 
00091 /// this class has 2 template dependencies: B and D. It contains a
00092 /// static boolean value that will be true if D is derived from B and
00093 /// false otherwise.
00094 ///
00095 /// Note: This construct may have a problem with MSVC7.1. See the
00096 /// boost implementation for a description and workaround
00097 /// \endif
00098 template<typename B, typename D>
00099 struct IsBaseAndDerived{
00100 #if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000))
00101 #pragma warning(push)
00102 #pragma warning(disable:6334)
00103 #endif
00104 
00105 
00106   /// \if internal_doc
00107   /// a helper structure that will pick between a casting to B*const
00108   /// or D.
00109   ///
00110   /// precisely how this structure works involves advanced C++
00111   /// conversion rules
00112   /// \endif
00113   struct Host{
00114 #if !((_MSC_VER !=0 ) && (_MSC_VER == 1310))
00115     operator B const volatile *() const;
00116 #else
00117     operator B const volatile * const&() const;
00118 #endif
00119     operator D const volatile *();
00120   };
00121 
00122   /// the boolean value being true if D is derived from B
00123   static const bool value = ((sizeof(B)!=0) && (sizeof(D)!=0) && (sizeof(__inheritance_helper<B,D>::check_sig(Host(), 0)) == sizeof(__yes_type)));
00124 
00125 #if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000))
00126 #pragma warning(pop)
00127 #endif
00128 };
00129 
00130 FASTJET_END_NAMESPACE
00131 
00132 
00133 #endif  // __IS_BASE_OF_HH__