FastJet 3.0beta1
IsBase.hh
00001 //STARTHEADER
00002 // $Id: IsBase.hh 2191 2011-06-01 07:42:54Z soyez $
00003 //
00004 // Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
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, write to the Free Software
00026 //  Foundation, Inc.:
00027 //      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028 //----------------------------------------------------------------------
00029 //ENDHEADER
00030 
00031 #ifndef __FASTJET_INTERNAL_IS_BASE_HH__
00032 #define __FASTJET_INTERNAL_IS_BASE_HH__
00033 
00034 #include "fastjet/internal/numconsts.hh"
00035 
00036 FASTJET_BEGIN_NAMESPACE
00037 
00038 //---------------------------------------------------
00039 // define a true and a false 'type'
00040 // Note: 
00041 //  we could actually template the type and recover 
00042 //  the TR1 integral_constant type. This also 
00043 //  includes adding a typedef for the type and a
00044 //  typedef for the struct in the struct below
00045 //
00046 // This is going to be helpful to "split" a given 
00047 // call into 2 options based on a type constraint
00048 // at compilation-time (rather than doing an "if" 
00049 // which would only be resolved at runtime and could
00050 // thus resutl in compilation errors. 
00051 //---------------------------------------------------
00052 
00053 /// \if internal_doc
00054 /// \class integral type 
00055 /// a generic construct that promotes a generic value of a generic type
00056 /// as a type
00057 ///
00058 /// this has 2 template parameters: T, the considered type, and _t, a
00059 /// value of type T
00060 /// This object is a basic construct in type traits
00061 /// \endif
00062 template<typename T, T _t>
00063 struct integral_type{
00064   static const T value = _t;         ///< the value (only member carrying info)
00065   typedef T value_type;              ///< a typedef for the type T
00066   typedef integral_type<T,_t> type;  ///< a typedef for the whole structure
00067 };
00068 
00069 // definition of the static member in integral_type
00070 template<typename T, T _t>
00071 const T integral_type<T, _t>::value;
00072 
00073 // shortcuts
00074 typedef integral_type<bool, true>  true_type;  ///< the bool 'true'  value promoted to a type
00075 typedef integral_type<bool, false> false_type; ///< the bool 'false' value promoted to a type
00076 
00077 
00078 //---------------------------------------------------
00079 // define a yes and a no type (based on their size)
00080 //---------------------------------------------------
00081 typedef char (&__yes_type)[1]; //< the yes type
00082 typedef char (&__no_type) [2]; //< the no type
00083 
00084 
00085 //---------------------------------------------------
00086 // Now deal with inheritance checks
00087 //
00088 // We want to provide a IsBaseAndDerived<B,D> type 
00089 // trait that contains a value that is true if D
00090 // is derived from B and false otherwise.
00091 //
00092 // For an explanation of how the code below works, 
00093 // have a look at 
00094 //   http://groups.google.com/group/comp.lang.c++.moderated/msg/dd6c4e4d5160bd83
00095 // and the links therein
00096 //
00097 // WARNING: according to 'boost', this may have some
00098 //   issues with MSVC7.1. See their code for a description
00099 //   of the workaround used below
00100 //---------------------------------------------------
00101 
00102 /// \if internal_doc
00103 /// \class __inheritance_helper
00104 /// helper for IsBasedAndDerived<B,D>
00105 /// \endif
00106 template<typename B, typename D>
00107 struct __inheritance_helper{
00108 #if !((_MSC_VER !=0 ) && (_MSC_VER == 1310))   // MSVC 7.1
00109   template <typename T>
00110   static __yes_type check_sig(D const volatile *, T);
00111 #else
00112   static __yes_type check_sig(D const volatile *, long);
00113 #endif
00114   static __no_type  check_sig(B const volatile *, int);
00115 };
00116 
00117 /// \if internal_doc
00118 /// \class IsBaseAndDerived
00119 /// check if the second template argument is derived from the first one
00120 /// 
00121 /// this class has 2 template dependencies: B and D. It contains a
00122 /// static boolean value that will be true if D is derived from B and
00123 /// false otherwise.
00124 ///
00125 /// Note: This construct may have a problem with MSVC7.1. See the
00126 /// boost implementation for a description and workaround
00127 /// \endif
00128 template<typename B, typename D>
00129 struct IsBaseAndDerived{
00130 #if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000))
00131 #pragma warning(push)
00132 #pragma warning(disable:6334)
00133 #endif
00134 
00135 
00136   /// \if internal_doc
00137   /// a helper structure that will pick between a casting to B*const
00138   /// or D.
00139   ///
00140   /// precisely how this structure works involves advanced C++
00141   /// conversion rules
00142   /// \endif
00143   struct Host{
00144 #if !((_MSC_VER !=0 ) && (_MSC_VER == 1310))
00145     operator B const volatile *() const;
00146 #else
00147     operator B const volatile * const&() const;
00148 #endif
00149     operator D const volatile *();
00150   };
00151 
00152   /// the boolean value being true if D is derived from B
00153   static const bool value = ((sizeof(B)!=0) && 
00154                              (sizeof(D)!=0) && 
00155                              (sizeof(__inheritance_helper<B,D>::check_sig(Host(), 0)) == sizeof(__yes_type)));
00156 
00157 #if ((_MSC_FULL_VER != 0) && (_MSC_FULL_VER >= 140050000))
00158 #pragma warning(pop)
00159 #endif
00160 };
00161 
00162 
00163 /// a little helper that returns a pointer to d of type B* if D is
00164 /// derived from B and NULL otherwise
00165 template<class B, class D>
00166 B* cast_if_derived(D* d){
00167   return IsBaseAndDerived<B,D>::value ? (B*)(d) : NULL;
00168 }
00169 
00170 
00171 FASTJET_END_NAMESPACE
00172 
00173 
00174 #endif  // __IS_BASE_OF_HH__
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends