00001 /*! A CreateFunctor is a Functor which creates an object with optional 00002 parameters. The parameter manipulation and object creation are 00003 dissacociated, so that at the point of object creation parameter 00004 type and value need not be known. 00005 */ 00006 ////////////////////////////////////////////////////////////////////////// 00007 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00008 // University of Southern California (USC) and the iLab at USC. // 00009 // See http://iLab.usc.edu for information about this project. // 00010 ////////////////////////////////////////////////////////////////////////// 00011 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00012 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00013 // in Visual Environments, and Applications'' by Christof Koch and // 00014 // Laurent Itti, California Institute of Technology, 2001 (patent // 00015 // pending; application number 09/912,225 filed July 23, 2001; see // 00016 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00017 ////////////////////////////////////////////////////////////////////////// 00018 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00019 // // 00020 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00021 // redistribute it and/or modify it under the terms of the GNU General // 00022 // Public License as published by the Free Software Foundation; either // 00023 // version 2 of the License, or (at your option) any later version. // 00024 // // 00025 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00026 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00027 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00028 // PURPOSE. See the GNU General Public License for more details. // 00029 // // 00030 // You should have received a copy of the GNU General Public License // 00031 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00032 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00033 // Boston, MA 02111-1307 USA. // 00034 ////////////////////////////////////////////////////////////////////////// 00035 // 00036 // Primary maintainer for this file: David J. Berg <dberg@usc.edu> 00037 // $HeadURL:svn://ilab.usc.edu/trunk/saliency/src/GenericUtils/CreateFunctor.H$ 00038 00039 #ifndef UTIL_CREATEFUNCTOR_H_DEFINED 00040 #define UTIL_CREATEFUNCTOR_H_DEFINED 00041 00042 #ifdef INVT_USE_CPPOX//we need c++ 0X features for this to work 00043 00044 #include "GenericUtils/ParamList.H" 00045 #include "GenericUtils/ObjCreator.H" 00046 #include "Util/log.H" 00047 00048 #include <typeinfo> 00049 00050 //###################################################################### 00051 //CreateListHolder 00052 // 00053 // This is an abstract class to represent interface to various 00054 // CreateListHolderImpl's which will hold ParamList's for object 00055 // creation. See CreatListHolderImpl for the implementation and 00056 // CreateFunctor which uses a CreateListHolder. MutPlist must be 00057 // a ParamList<typename...> Users should not use this class directly. 00058 //###################################################################### 00059 template <class ReturnType, class MutPlist> 00060 class CreateListHolder 00061 { 00062 public: 00063 //destructor 00064 virtual ~CreateListHolder() { }; 00065 00066 //create a ReturnType 00067 virtual ReturnType* create() const = 0; 00068 00069 //polymorphicly clone the object 00070 virtual CreateListHolder* clone() const 00071 { 00072 CreateListHolder* d = doClone(); 00073 if ( typeid(*d) != typeid(*this) ) 00074 LFATAL("DoClone incorrectly overridden" ); 00075 return d; 00076 }; 00077 00078 //update the mutable paramters 00079 template <typename... Params> 00080 void setMutParams(const Params&... params) 00081 { 00082 itsMutParams = ParamList<Params...>(params...); 00083 } 00084 00085 //update the mutable params in the paramlist 00086 virtual bool update() = 0; 00087 00088 protected: 00089 //constructors and assignment 00090 CreateListHolder() : itsMutParams() { }; 00091 CreateListHolder(const MutPlist& mutplist) : itsMutParams(mutplist) { }; 00092 CreateListHolder(const CreateListHolder& rhs) : itsMutParams(rhs.itsMutParams) { }; 00093 CreateListHolder& operator=(const CreateListHolder& rhs) 00094 { if (this != &rhs) itsMutParams = rhs.itsMutParams; return *this; }; 00095 00096 MutPlist itsMutParams;//our mutable parameter list 00097 00098 private: 00099 virtual CreateListHolder* doClone() const = 0; 00100 }; 00101 00102 //###################################################################### 00103 // CreateListHolderImpl 00104 // 00105 // The polymorphic implementation of CreateListHolder. This class 00106 // stores parameter information used in CreateFunctor. Different 00107 // template instantiations will create different derived types all 00108 // accesable through the CreateListHolder interface. MutPlist must be 00109 // a ParamList<typename...> Users should not use this class directly. 00110 // ###################################################################### 00111 template <class ReturnType, class CreateType, class MutPlist, typename... Params> class CreateListHolderImpl; 00112 00113 //specialization for when there are no parameters 00114 //###################################################################### 00115 template <class ReturnType, class CreateType, class MutPlist> 00116 class CreateListHolderImpl<ReturnType,CreateType,MutPlist> : public CreateListHolder<ReturnType, MutPlist> 00117 { 00118 public: 00119 //constructor 00120 CreateListHolderImpl() : CreateListHolder<ReturnType, MutPlist>() { }; 00121 00122 //default copy constructor and assignment OK 00123 00124 //desctructor 00125 virtual ~CreateListHolderImpl() { }; 00126 00127 //create an object of type ReturnType 00128 ReturnType* create() const 00129 { return new CreateType(); } 00130 00131 //update the mutable params in the paramlist, return true if an update could be made 00132 virtual bool update() 00133 { 00134 return false; 00135 } 00136 00137 private: 00138 //actually do the work of clone() 00139 CreateListHolderImpl<ReturnType, CreateType, MutPlist>* doClone() const 00140 { 00141 return new CreateListHolderImpl<ReturnType, CreateType, MutPlist>(*this); 00142 }; 00143 }; 00144 00145 //specialization for when there are N parameters 00146 //###################################################################### 00147 template <class ReturnType, class CreateType, class MutPlist, typename... Params> 00148 class CreateListHolderImpl : public CreateListHolder<ReturnType, MutPlist> 00149 { 00150 public: 00151 //constructor 00152 CreateListHolderImpl(const ParamList<Params...>& paramlist) 00153 : CreateListHolder<ReturnType, MutPlist>(), itsList(paramlist) { }; 00154 00155 //constructor 00156 CreateListHolderImpl(const Params&... params) 00157 : CreateListHolder<ReturnType, MutPlist>(), itsList(params...) { }; 00158 00159 //default copy constructor and assignment OK 00160 00161 //desctructor 00162 virtual ~CreateListHolderImpl() { }; 00163 00164 //create an object of type ReturnType 00165 ReturnType* create() const 00166 { return ObjCreator<CreateType>::create(itsList); } 00167 00168 //update the mutable params in the paramlist, return true if an update could be made 00169 virtual bool update() 00170 { 00171 return itsList.assign(CreateListHolder<ReturnType, MutPlist>::itsMutParams); 00172 } 00173 00174 private: 00175 //actually do the work of clone() 00176 CreateListHolderImpl<ReturnType, CreateType, MutPlist, Params...>* doClone() const 00177 { 00178 return new CreateListHolderImpl<ReturnType, CreateType, MutPlist, Params...>(*this); 00179 }; 00180 00181 ParamList<Params...> itsList;//hold our ParamList 00182 }; 00183 00184 //###################################################################### 00185 // CreateFunctor is a functor that creates an object with optional parameters. The parameter manipulation and object 00186 // creation are dissacociated, so that at the point of object creation parameter type and value need not be known. 00187 // Parameters can be set at functor creation and modified later if desired. A call to operator() will return the desired 00188 // type. The is particularly useful with GenericFactory.H 'ReturnType' is the type of object to return (could be an 00189 // abstract class). The second template must be a ParamList whose types are the types of the mutable parameters, which 00190 // could be a subset of the parameters used to create the object. The result is some fixed and some mutable parameters. 00191 // See UpdateParams() for more details. 00192 // 00193 // Usage: 00194 // 00195 //Imagine we have a class Circle which can take one or two arguments and 00196 //derives from Shape. operator() prints "I'm a Cicle". Circle has two 00197 //public members p1, and p2 to hold the arguments. 00198 00199 // //test functor components 00200 // ParamList<float,int> pl(1.00f, 1); 00201 // CreateFunctor<Circle> func(pl); 00202 // Circle* c = func(); 00203 // LINFO("%3.2f, %d", c->p1, c->p2); 00204 00205 // //create Functor from parameters 00206 // CreateFunctor<Circle> func1(2.00f, 2); 00207 // CreateFunctor<Circle> func2(10.10f); 00208 // c = func1(); 00209 // LINFO("%3.2f, %d", c->p1, c->p2); 00210 // c = func2(); 00211 // LINFO("%3.2f, %d", c->p1, c->p2); 00212 00213 // //now, create a derived type of the return type 00214 // auto func3 = CreateFunctor<Shape>::make<Circle>(pl); 00215 // Shape* s = func3(); 00216 // (*s)(); //print the message 00217 // c = dynamic_cast<Circle*>(s);//cast to a circle 00218 // LINFO("%3.2f, %d", c->p1, c->p2); 00219 00220 // //make from some params instead 00221 // auto func4 = CreateFunctor<Shape>::make<Circle>(33.33f, 55); 00222 // s = func4(); 00223 // (*s)(); //print the message 00224 // c = dynamic_cast<Circle*>(s); 00225 // LINFO("%3.2f, %d", c->p1, c->p2); 00226 // 00227 // //update both parameter. see updateParams() for more details 00228 // CreateFunctor<Circle,ParamList<float,int> > func5(2.00f, 2); 00229 // func5.updateParams(0.0f,0); 00230 // c = func5(); 00231 // LINFO("%3.2f, %d", c->p1, c->p2); 00232 // 00233 // //only the second paramter is able to be changed 00234 // CreateFunctor<Circle,ParamList<int> > func6(2); 00235 // func6.updateParams(0); 00236 // c = func6(); 00237 // LINFO("%3.2f, %d", c->p1, c->p2); 00238 // ###################################################################### 00239 template <class ReturnType, class MutPlist = ParamList<>> 00240 class CreateFunctor 00241 { 00242 public: 00243 //empty creation function- particularly when we want to create a derived type and return a base class pointer. 00244 template<class CreateType> 00245 static CreateFunctor<ReturnType, MutPlist> make() 00246 { 00247 CreateListHolderImpl<ReturnType, CreateType, MutPlist> temp; 00248 return CreateFunctor<ReturnType, MutPlist>(temp); 00249 }; 00250 00251 //static creation function which takes a paramlist 00252 template<class CreateType, typename... Params> 00253 static CreateFunctor<ReturnType, MutPlist> make(const ParamList<Params...>& paramlist) 00254 { 00255 CreateListHolderImpl<ReturnType, CreateType, MutPlist, Params...> temp(paramlist); 00256 return CreateFunctor<ReturnType, MutPlist>(temp); 00257 }; 00258 00259 //static creation function which takes params 00260 template<class CreateType, typename... Params> 00261 static CreateFunctor<ReturnType, MutPlist> make(const Params&... params) 00262 { 00263 CreateListHolderImpl<ReturnType, CreateType, MutPlist, Params...> temp(params...); 00264 return CreateFunctor<ReturnType, MutPlist>(temp); 00265 }; 00266 00267 //constructor 00268 CreateFunctor() 00269 : itsPLH(new CreateListHolderImpl<ReturnType, ReturnType, MutPlist>()) 00270 { }; 00271 00272 //construct from a param list 00273 template<typename... Params> 00274 CreateFunctor(const ParamList<Params...>& paramlist) 00275 : itsPLH(new CreateListHolderImpl<ReturnType, ReturnType, MutPlist, Params...>(paramlist)) 00276 { }; 00277 00278 //construct from parameters 00279 template<typename... Params> 00280 CreateFunctor(const Params&... params) 00281 : itsPLH(new CreateListHolderImpl<ReturnType, ReturnType, MutPlist, Params...>(params...)) 00282 { }; 00283 00284 //copy constructor 00285 CreateFunctor(const CreateFunctor<ReturnType, MutPlist>& rhs) 00286 : itsPLH( (rhs.itsPLH) ? rhs.itsPLH->clone() : NULL ) { }; 00287 00288 //destructor 00289 ~CreateFunctor() {delete itsPLH; }; 00290 00291 //assignment operator 00292 CreateFunctor<ReturnType, MutPlist>& operator=(const CreateFunctor<ReturnType, MutPlist>& rhs) 00293 { 00294 if (this != &rhs) 00295 { 00296 if (itsPLH) delete itsPLH; 00297 itsPLH = (rhs.itsPLH) ? rhs.itsPLH->clone() : NULL; 00298 } 00299 }; 00300 00301 //function call operator 00302 ReturnType* operator()() const { return (itsPLH) ? itsPLH->create() : NULL; }; 00303 00304 //update our mutable parameters and return true if an update could be made. This relies on the 'assign' function of 00305 //the ParamList used as the second template type. So, only a subset of paramters can be assigned (ie Params does not 00306 //have to be all the possible parameters the object being created could take). See ParamList.H. 00307 template <typename... Params> 00308 bool updateParams(const Params&... params) 00309 { 00310 itsPLH->setMutParams(params...); 00311 return itsPLH->update(); 00312 } 00313 00314 private: 00315 //construct from a CreateListHolderImpl 00316 template<class CreateType, typename... Params> 00317 CreateFunctor(const CreateListHolderImpl<ReturnType, CreateType, MutPlist, Params...>& clhi) : itsPLH(clhi.clone()) 00318 { }; 00319 00320 //pointer to a CreateListHolderImpl 00321 CreateListHolder<ReturnType, MutPlist>* itsPLH; 00322 }; 00323 00324 #endif //INVT_USE_CPPOX 00325 #endif//UTIL_CREATEFUNCTOR_H_DEFINED