Cmp.hh

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #ifndef RIVET_Cmp_HH
00003 #define RIVET_Cmp_HH
00004 
00005 #include "Rivet/Rivet.hh"
00006 #include "Rivet/Projection.hh"
00007 #include "Cmp.fhh"
00008 #include <typeinfo>
00009 
00010 
00011 namespace Rivet {
00012 
00013    /// Cmp is a helper class to be used when checking the ordering of two
00014    /// objects. When implicitly converted to an integer the value will be
00015    /// negative if the two objects used in the constructor are ordered and
00016    /// positive if they are not. Zero will be returned if they are equal.
00017    ///
00018    /// The main usage of the Cmp class is if several variables should be
00019    /// checked for ordering in which case several Cmp objects can be
00020    /// combined as follows: <code>cmp(a1, a2) || cmp(b1, b2) || cmp(c1,
00021    /// c2)</code> where cmp is a global function for easy creation of Cmp
00022    /// objects.
00023   template <typename T>
00024   class Cmp {
00025     
00026   public:
00027     
00028     /// Enumerate the possible states of a Cmp object.
00029     enum CmpState {
00030       undefined = -2,  //< Undefined state.
00031       ordered = -1,    //< The two corresponding objects are ordered.
00032       equivalent = 0,  //< The two corresponding objects are equivalent.
00033       unordered = 1    //< The two corresponding objects are unordered.
00034     };
00035     
00036   public:
00037     
00038     /// @name Standard constructors and destructors.
00039     //@{
00040     /// The default constructor.
00041     inline Cmp(const T & t1, const T & t2);
00042     
00043     /// The copy constructor.
00044     template <typename U>
00045     inline Cmp(const Cmp<U> &);
00046     
00047     /// The destructor is not virtual since this is not intended to be a base class.
00048     inline ~Cmp() {};
00049     
00050     /// The assignment operator.
00051     template <typename U>
00052     inline const Cmp<T> & operator=(const Cmp<U> &);
00053     
00054     //@}
00055     
00056   public:
00057     
00058     /// Automatically convert to an integer. 
00059     inline operator int () const;
00060     
00061     /// If this state is equivalent, set this state to the state of \a c.
00062     template <typename U>
00063     inline const Cmp<T> & operator||(const Cmp<U> & c) const;
00064     
00065   private:
00066     
00067     /// Perform the actual comparison if necessary.
00068     inline void compare() const;
00069     
00070   private:
00071     
00072     /// The state of this object.
00073     mutable int value;
00074     
00075     /// The objects to be compared.
00076     pair<const T *, const T *> objects;
00077     
00078   };
00079   
00080   /// Global helper function for easy creation of Cmp objects.
00081   template <typename T>
00082   inline Cmp<T> cmp(const T & t1, const T & t2) {
00083     return Cmp<T>(t1, t2);
00084   }
00085   
00086    /// Specialization of the Cmp helper class to be used when checking the
00087    /// ordering of two Projection objects. When implicitly converted to an
00088    /// integer the value will be negative if the two objects used in the
00089    /// constructor are ordered and positive if they are not. Zero will be
00090    /// returned if they are equal. This specialization uses directly the
00091    /// virtual compare() function in the Projection class.
00092    ///
00093    /// The main usage of the Cmp class is if several variables should be
00094    /// checked for ordering in which case several Cmp objects can be
00095    /// combined as follows: <code>cmp(a1, a2) || cmp(b1, b2) || cmp(c1,
00096    /// c2)</code> where cmp is a global function for easy creation of Cmp
00097    /// objects.
00098   template <>
00099   class Cmp<Projection> {
00100     
00101   public:
00102     
00103     /// Enumerate the possible states of a Cmp object.
00104     enum CmpState {
00105       undefined = -2, //< Undefined state.
00106       ordered = -1,   //< The two corresponding objects are ordered.
00107       equivalent = 0,  //< The two corresponding objects are equivalent.
00108       unordered = 1   //< The two corresponding objects are unordered.
00109     };
00110     
00111   public:
00112     
00113     /// @name Standard constructors and destructors.
00114     //@{
00115     /// The default constructor.
00116     inline Cmp(const Projection & p1, const Projection & p2);
00117     
00118     /// The copy constructor.
00119     template <typename U>
00120     inline Cmp(const Cmp<U> &);
00121     
00122      /// The destructor is not virtual since this is not intended to be a base class.
00123     inline ~Cmp() {};
00124     
00125      /// The assignment operator.
00126     template <typename U>
00127     inline const Cmp<Projection> & operator=(const Cmp<U> &);
00128     
00129     //@}
00130     
00131   public:
00132     
00133     /// Automatically convert to an integer. 
00134     inline operator int () const;
00135     
00136     /// If this state is equaivalent, set this state to the state of \a c.
00137     template <typename U>
00138     inline const Cmp<Projection> & operator||(const Cmp<U> & c) const;
00139     
00140   private:
00141     
00142     /// Perform the actual comparison if necessary.
00143     inline void compare() const;
00144     
00145   private:
00146     
00147     /// The state of this object.
00148     mutable int value;
00149     
00150     /// The objects to be compared.
00151     pair<const Projection *, const Projection *> objects;
00152     
00153   };
00154   
00155 
00156 
00157   /////////////////////////////////////////////////////////
00158 
00159 
00160 
00161    /// Global helper function for easy creation of Cmp objects.
00162   inline Cmp<Projection> pcmp(const Projection & p1, const Projection & p2) {
00163     return Cmp<Projection>(p1, p2);
00164   }
00165   
00166   
00167   template <typename T>
00168   inline Cmp<T>::Cmp(const T & t1, const T & t2)
00169     : value(undefined), objects(&t1, &t2) {}
00170   
00171   template <typename T>
00172   template <typename U>
00173   inline Cmp<T>::Cmp(const Cmp<U> & x)
00174     : value(x.operator int()), objects(0, 0) {}
00175   
00176   template <typename T>
00177   template <typename U>
00178   inline const Cmp<T> & Cmp<T>::operator=(const Cmp<U> & x) {
00179     value = x.operator int();
00180     return *this;
00181   }
00182   
00183   template <typename T>
00184   template <typename U>
00185   inline const Cmp<T> & Cmp<T>::operator||(const Cmp<U> & x) const {
00186     compare();
00187     if ( value == equivalent ) value = x.operator int();
00188     return *this;
00189   }
00190   
00191   template <typename T>
00192   inline Cmp<T>::operator int() const {
00193     compare();
00194     return value;
00195   }
00196   
00197   template <typename T>
00198   inline void Cmp<T>::compare() const {
00199     if ( value == undefined ) {
00200       less<T> l;
00201       if ( l(*objects.first, *objects.second) ) value = ordered;
00202       else if ( l(*objects.second, *objects.first) ) value = unordered;
00203       else value = equivalent;
00204     }
00205   }
00206   
00207   inline Cmp<Projection>::Cmp(const Projection & p1, const Projection & p2)
00208     : value(undefined), objects(&p1, &p2) {}
00209   
00210   template <typename U>
00211   inline Cmp<Projection>::Cmp(const Cmp<U> & x)
00212     : value(x.operator int()), objects(0, 0) {}
00213   
00214   template <typename U>
00215   inline const Cmp<Projection> & Cmp<Projection>::operator=(const Cmp<U> & x) {
00216     value = x.operator int();
00217     return *this;
00218   }
00219   
00220   template <typename U>
00221   inline const Cmp<Projection> &
00222   Cmp<Projection>::operator||(const Cmp<U> & x) const {
00223     compare();
00224     if ( value == equivalent ) value = x.operator int();
00225     return *this;
00226   }
00227   
00228   inline Cmp<Projection>::operator int() const {
00229     compare();
00230     return value;
00231   }
00232   
00233   inline void Cmp<Projection>::compare() const {
00234     if ( value == undefined ) {
00235       const std::type_info & id1 = typeid(*objects.first);
00236       const std::type_info & id2 = typeid(*objects.second);
00237       if ( id1.before(id2) ) value = ordered;
00238       else if ( id2.before(id1) ) value = unordered;
00239       else {
00240         int c = objects.first->compare(*objects.second);
00241         if ( c < 0 ) value = ordered;
00242         else if ( c > 0 ) value = unordered;
00243         else value = equivalent;
00244       }
00245     }
00246   }
00247   
00248    
00249 }
00250 
00251 
00252 #endif