ParamList.H

00001 /*! A ParamList is a statically sized array of arbitrary types */
00002 //////////////////////////////////////////////////////////////////////////
00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00004 // University of Southern California (USC) and the iLab at USC.         //
00005 // See http://iLab.usc.edu for information about this project.          //
00006 //////////////////////////////////////////////////////////////////////////
00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00009 // in Visual Environments, and Applications'' by Christof Koch and      //
00010 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00011 // pending; application number 09/912,225 filed July 23, 2001; see      //
00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00013 //////////////////////////////////////////////////////////////////////////
00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00015 //                                                                      //
00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00017 // redistribute it and/or modify it under the terms of the GNU General  //
00018 // Public License as published by the Free Software Foundation; either  //
00019 // version 2 of the License, or (at your option) any later version.     //
00020 //                                                                      //
00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00024 // PURPOSE.  See the GNU General Public License for more details.       //
00025 //                                                                      //
00026 // You should have received a copy of the GNU General Public License    //
00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00029 // Boston, MA 02111-1307 USA.                                           //
00030 //////////////////////////////////////////////////////////////////////////
00031 //
00032 // Primary maintainer for this file: David J. Berg <dberg@usc.edu>
00033 // $HeadURL:svn://ilab.usc.edu/trunk/saliency/src/Util/ParamList.H$
00034 
00035 #ifndef UTIL_PARAMLIST_H_DEFINED
00036 #define UTIL_PARAMLIST_H_DEFINED
00037 
00038 #ifdef INVT_USE_CPPOX//we need c++ 0X features for this to work
00039 
00040 //######################################################################
00041 //a type to represent an error - useful to coerce gcc to give better
00042 //error messages
00043 //######################################################################
00044 namespace paramlist_error
00045 {
00046   struct OutOfBounds { };
00047 }
00048 
00049 //######################################################################
00050 //declare ParamList and its base case - see ParamList below
00051 //######################################################################
00052 //declare the ParamList
00053 template <typename... Params> class ParamList;
00054 
00055 //ParamList class - base case in template recursion - see ParamList below
00056 //######################################################################
00057 template <> class ParamList<>
00058 {   
00059 public:
00060   //typedefs 
00061   typedef paramlist_error::OutOfBounds ParamType;
00062   typedef paramlist_error::OutOfBounds BaseType;
00063 
00064   //the length of our type array
00065   enum {length = 0};
00066   
00067   //set the current params
00068   void setParams() { };
00069   
00070   //assign another paramlist to this one, return true if something is assigned. 
00071   //This ones for when both paramlists are empty
00072   bool assign(const ParamList<>& rhs, int count = 0) { return (count > 0) ? true : false; };
00073   
00074   //assign another paramlist to this one, return true if something is assigned.
00075   //this ones for when the rhs actually has paramters
00076   template<typename... Params>
00077   bool assign(const ParamList<Params...>& rhs, int count = 0) { return false; };
00078   
00079   //defining this function and the dummy parameter are not necessary
00080   //but allows for more intelligable gcc errors if we attempt to
00081   //access outside the length of ParamList. Basically, allow
00082   //everything to work and then get an assignment error when we try to
00083   //assign our bogus paramlist_error::OutOfBounds class to an actual
00084   //type.
00085   ParamType& head() {return parameter; };
00086   const ParamType& head() const {return parameter; };
00087 
00088   //get the tail, which is just itself. 
00089   ParamList& tail() {return *this; };
00090   const ParamList& tail() const {return *this; };
00091 
00092 private: 
00093   ParamType parameter;//a dummy variable for head()
00094 };
00095 
00096 //######################################################################
00097 //a helper class to get the entries at locations in the
00098 //ParamList. ParamEntry gets entry at the desired depth, and
00099 //ParamEntryType gets the entry that matches the desired type.
00100 //######################################################################
00101 namespace ParamListHelper
00102 {
00103   //######################################################################
00104   //make a parameter list
00105   //######################################################################
00106   template <class... Params> 
00107   ParamList<Params...> make_paramlist(const Params&... params)
00108   {
00109     return ParamList<Params...>(params...);
00110   }
00111   
00112   //######################################################################
00113   //get the parameter at the specifed location.
00114   //######################################################################
00115   template <uint depth, class... Params> struct ParamEntry;
00116 
00117   //get the parameter at the specifed location - error case
00118   //######################################################################
00119   template <uint depth> 
00120   struct ParamEntry<depth>
00121   {
00122     typedef paramlist_error::OutOfBounds ParamType;
00123     
00124     //return an error class
00125     static ParamType& value(ParamList<>& pfunc) 
00126     {
00127       return pfunc.head();
00128     };
00129 
00130     static const ParamType& value(const ParamList<>& pfunc) 
00131     {
00132       return pfunc.head();
00133     };
00134   };  
00135 
00136   //get the parameter at the specifed location - base case
00137   //######################################################################
00138   template <class Head, class... Params> 
00139   struct ParamEntry<0, Head, Params...>
00140   {
00141     //the type of our paramter at position 0
00142     typedef Head ParamType;
00143 
00144     //value of paramter at position 0
00145     static ParamType& value(ParamList<Head, Params...>& pfunc) 
00146     {
00147       return pfunc.head();
00148     };
00149 
00150     //value of paramter at position 0 - const version
00151     static const ParamType& value(const ParamList<Head, Params...>& pfunc)
00152     {
00153       return pfunc.head();
00154     };
00155   };
00156   
00157   //get the parameter at the specifed location - recursive case
00158   //######################################################################
00159   template <uint depth, class Head, class... Params> 
00160   struct ParamEntry<depth, Head, Params...>
00161   {
00162     //get the parameter type at depth-1
00163     typedef typename ParamEntry<depth-1, Params...>::ParamType ParamType;
00164     
00165     //return the value at depth-1
00166     static ParamType& value(ParamList<Head, Params...>& pfunc) 
00167     {
00168       return ParamEntry<depth-1, Params...>::value(pfunc.tail());
00169     };
00170     
00171     //return the value at depth-1 - const version
00172     static const ParamType& value(const ParamList<Head, Params...>& pfunc)
00173     {
00174       return ParamEntry<depth-1, Params...>::value(pfunc.tail());
00175     };
00176   };  
00177   
00178   //######################################################################
00179   //get the parameter at the first matching type
00180   //######################################################################
00181   template <typename T, typename... Params> struct ParamEntryType;
00182 
00183   //give a better error message if the item is not found
00184   //######################################################################
00185   template <typename T> 
00186   struct ParamEntryType<T>
00187   {
00188     typedef paramlist_error::OutOfBounds ParamType;
00189    
00190     //return an error class
00191     static ParamType& value(ParamList<>& pfunc) 
00192     {
00193       return pfunc.head();
00194     };
00195 
00196     static const ParamType& value(const ParamList<>& pfunc) 
00197     {
00198       return pfunc.head();
00199     };
00200   };
00201 
00202   //match case
00203   //######################################################################
00204   template <typename T, typename... Params> 
00205   struct ParamEntryType<T, T, Params...>
00206   {
00207     typedef T ParamType;
00208     
00209     //return the value at head
00210     static ParamType& value(ParamList<T, Params...>& pfunc) 
00211     {
00212       return pfunc.head();
00213     };
00214     
00215     //return the value at head - const version
00216     static const ParamType& value(const ParamList<T, Params...>& pfunc)
00217     {
00218       return pfunc.head();
00219     };
00220   };  
00221 
00222   //get the parameter at the first matching type - recursive case
00223   //######################################################################
00224   template <typename T, typename Head, typename... Params> 
00225   struct ParamEntryType<T, Head, Params...>
00226   {
00227     //typedef
00228     typedef T ParamType;
00229     
00230     //get the parameter value
00231     static ParamType& value(ParamList<Head, Params...>& pfunc) 
00232     {
00233       return ParamEntryType<T, Params...>::value(pfunc.tail()); 
00234     };
00235     
00236     //get the parameter value - const version
00237     static const ParamType& value(const ParamList<Head, Params...>& pfunc)
00238     {
00239       return ParamEntryType<T, Params...>::value(pfunc.tail()); 
00240     };
00241   };  
00242 
00243   //######################################################################
00244   //convenient access functions
00245   //######################################################################
00246 
00247   //get the parameter at the specifed location.
00248   //######################################################################
00249   template <uint depth, typename Head, typename... Params>
00250   typename ParamEntry<depth, Head, Params...>::ParamType& at(ParamList<Head, Params...>& paramlist)
00251   {
00252     return ParamEntry<depth, Head, Params...>::value(paramlist);
00253   }
00254 
00255   //get the parameter at the specifed location - const versin
00256   //######################################################################
00257   template <uint depth, typename Head, typename... Params>
00258   const typename ParamEntry<depth, Head, Params...>::ParamType& at(const ParamList<Head, Params...>& paramlist)
00259   {
00260     return ParamEntry<depth, Head, Params...>::value(paramlist);
00261   }
00262 
00263   //get the parameter with the specified type.
00264   //######################################################################
00265   template <typename T, typename Head, typename... Params>
00266   T& at(ParamList<Head, Params...>& paramlist)
00267   {
00268     return ParamEntryType<T, Head, Params...>::value(paramlist);
00269   }
00270 
00271   //get the parameter with the specifed type - const versin
00272   //######################################################################
00273   template <typename T, typename Head, typename... Params>
00274   const T& at(const ParamList<Head, Params...>& paramlist)
00275   {
00276     return ParamEntryType<T, Head, Params...>::value(paramlist);
00277   }
00278 }//end namespace
00279 
00280 //######################################################################
00281 // ParamList class
00282 //
00283 // An array of arbitrary types. Types and length must be determined at
00284 // compile-time but values can be set at runtime. Useful to pass
00285 // paramter information around.
00286 //
00287 // Usage:
00288 // 
00289 //  using namespace ParamListHelper;
00290 //
00291 //  //create a paramlist and prints its values
00292 //  ParamList<float,int,double> fun(1.1f, 2, 1.2);
00293 //  LINFO("%3.2f, %d, %3.2f", at<0>(fun), at<1>(fun), at<2>(fun));
00294 //
00295 //  //reset params
00296 //  fun.setParams(0.0f, 0, 0.0);
00297 //  LINFO("%3.2f, %d, %3.2f", at<0>(fun), at<1>(fun), at<2>(fun));
00298 
00299 //  //another way to create and access
00300 //  auto fun1 = make_paramlist(14.4F,3);
00301 //  at<0>(fun1) = 5.5F; //assign a value
00302 //  float f = at<0>(fun1); //retrive a value by number
00303 //  int i = at<int>(fun1); //retrive by type (first matching)
00304 //  LINFO("%3.3f, %d", f, i);
00305 //
00306 // //just reassign a subset of the parameters 
00307 // ParamList<float,int,double,float> p(0.0f,0,0.0,0.0f);
00308 // ParamList<int,double> p1(1,1.0);
00309 // p.assign(p1); //The second and third parameters will be set to 1 and 1.0, resp. 
00310 //
00311 //Notes: 
00312 // 1) If assignment is called on two lists with no pattern shared the operation 
00313 // will silently do nothing. The whole rhs pattern must be matched with a subpattern
00314 // on the lhs. 
00315 
00316 // 2)This implementation does not support references, but could
00317 // with some simple type traits.
00318 //######################################################################
00319 
00320 //ParamList class - recursive case in template recursion
00321 //######################################################################
00322 template <typename Head, typename... Params>
00323 class ParamList<Head, Params...> : private ParamList<Params...>
00324 {
00325 public:
00326   //typedefs    
00327   typedef Head ParamType;
00328   typedef ParamList<Params...> BaseType;
00329 
00330   //the length of our type array
00331   enum {length = sizeof...(Params) + 1};
00332 
00333   //empty constructor 
00334   ParamList() : ParamList<Params...>(), parameter(Head()) { };
00335   
00336   //constructor 
00337   ParamList(const Head& head, const Params&... params) 
00338   : ParamList<Params...>(params...), parameter(head) { };
00339 
00340   //default copy ctor OK
00341   
00342   //destructor
00343   ~ParamList() { };
00344   
00345   //set the parameters
00346   void setParams(const Head& head, const Params&... params)
00347   {
00348     parameter = head;
00349     BaseType::setParams(params...);
00350   };
00351  
00352   //Assign a list. The rhs may have a different number or type of arguments. 
00353   //The first type sub-pattern that matches the rhs type pattern will be assigned. 
00354   //If no match occurs the operation does nothing. Return true if something 
00355   //is assigned. 
00356   
00357   //base case, for when the rhs is empty, return true if something is assigned. 
00358   bool assign(const ParamList<>& rhs, int count = 0) { return (count > 0) ? true : false;}
00359   
00360   //match case
00361   template <typename... Types>
00362   bool assign(const ParamList<Head, Types...>& rhs, int count = 0)
00363   {
00364     bool temp = tail().assign(rhs.tail(), ++count);
00365     if (temp == true)
00366       parameter = rhs.head();
00367     return temp;
00368   }
00369   
00370   //no match case
00371   template <typename... Types>
00372   bool assign(const ParamList<Types...>& rhs, int count = 0)
00373   {
00374     if (count > 0) 
00375       return false;
00376     return tail().assign(rhs, count);
00377   }
00378   
00379   //get the head of the list
00380   ParamType& head() {return parameter; };
00381   const ParamType& head() const {return parameter; };
00382   
00383   //get the tail of the list (taking advantage of slicing of *this)
00384   BaseType& tail() {return *this; };
00385   const BaseType& tail() const {return *this; };
00386   
00387 private:  
00388   Head parameter;//parameter for this level in the list
00389 };
00390 
00391 #endif //INVT_USE_CPPOX
00392 #endif//UTIL_PARAMLIST_H_DEFINED
Generated on Sun May 8 08:40:39 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3