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