ModelParam.H

Go to the documentation of this file.
00001 /*!@file Component/ModelParam.H A template ModelComponent parameter class */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Component/ModelParam.H $
00035 // $Id: ModelParam.H 8782 2007-09-20 22:34:54Z rjpeters $
00036 //
00037 
00038 #ifndef MODELPARAM_H_DEFINED
00039 #define MODELPARAM_H_DEFINED
00040 
00041 #include "Component/ModelParamBase.H"
00042 #include "Component/ParamClient.H"
00043 #include "Component/ParamFlags.H"
00044 #include "Util/StringConversions.H"
00045 #include "rutz/fileposition.h" // for SRC_POS
00046 #include "rutz/mutex.h"
00047 #include "rutz/shared_ptr.h"
00048 #include "rutz/stderror.h" // for rutz::throw_bad_cast()
00049 
00050 #include <iosfwd>
00051 #include <string>
00052 #include <typeinfo>
00053 
00054 #include <pthread.h>
00055 
00056 class ModelOptionDef;
00057 class ParamMap;
00058 
00059 // ######################################################################
00060 //! Helper implementation class for NModelParam and OModelParam
00061 class ModelParamAuxImpl
00062 {
00063 public:
00064   //! Construct from a ModelOptionDef*
00065   /*! This model param will get its name from the ModelOptionDef*.
00066 
00067       @param self pointer to the object that is using this impl
00068       @param client the ParamClient we are attached to
00069       @param nam the name of the TModelParamBase, that will be used to
00070          store its value in a ParamMap and fetch command-line option
00071          configuration data.
00072       @param flags can be set to USE_MY_VAL in order to take this
00073          param's value as the new default value, otherwise pass 0 for flags
00074       @param valtype the typeid of the parameter; we will check to
00075          make sure this matches the typeid declared by the
00076          ModelOptionDef
00077   */
00078   ModelParamAuxImpl(OptionedModelParam* self,
00079                     const ModelOptionDef* def,
00080                     ParamClient* client,
00081                     const ParamFlag flags,
00082                     const std::type_info& valtype);
00083 
00084   //! Construct with a string name only
00085   /*! This model param will NOT be associated with any ModelOptionDef
00086       -- to get that, use the other constructor that takes a
00087       ModelOptionDef* instead of a name.
00088 
00089       @param self pointer to the object that is using this impl
00090       @param client the ParamClient we are attached to
00091       @param nam the name of the ModelParamAuxImpl, that will be used to
00092          store its value in a ParamMap and fetch command-line option
00093          configuration data. */
00094   ModelParamAuxImpl(ModelParamBase* self,
00095                     const std::string& nam, ParamClient* client);
00096 
00097   //! Destructor
00098   ~ModelParamAuxImpl();
00099 
00100   //! get the ModelParamAuxImpl's name
00101   std::string getName() const;
00102 
00103   //! get the associated option def
00104   const ModelOptionDef* getOptionDef() const;
00105 
00106   //! Print out our name and contents, mostly for debugging
00107   void printout(std::ostream& s, const std::string& prefix) const;
00108 
00109   //! Write parameter value to ParamMap
00110   void writeTo(ParamMap& pmap) const;
00111 
00112   //! Get parameter value from ParamMap
00113   /*! @param noerr will not generate an error message if the parameter
00114       does not exist in ParamMap. */
00115   void readFrom(const ParamMap& pmap, const bool noerr);
00116 
00117   //! Call paramChanged() on our client
00118   ParamClient::ChangeStatus sendChangedMessage(bool didchange);
00119 
00120   //! Convenience function to retrieve def->defval.
00121   /*! The reason we have this here is so that we don't have to
00122       #include ModelOptionDef.H from this widely-used header file. */
00123   static const char* defaultValueOf(const ModelOptionDef* def);
00124 
00125   //! Get a mutex for locking the parameter value for reading
00126   /*! We only return an actual mutex if we were passed
00127       ALLOW_ONLINE_CHANGES in our constructor (i.e.,
00128       ModelParamBase::allowsOnlineChanges() returns true); that's
00129       because we assume that if online parameter changes are disabled,
00130       then there is no need for between-thread synchronization of our
00131       parameter value.
00132 
00133       The returned mutex, if non-null, will be a recursive mutex so
00134       that we can allow reentrant calls to getVal() from within a
00135       setVal() in the same thread, while still blocking getVal() calls
00136       from other threads during a setVal() call.
00137   */
00138   pthread_mutex_t* readLock() const
00139   { return itsLocks ? &itsLocks[READLOCK] : 0; }
00140 
00141   //! Get a mutex for locking the parameter value for writing
00142   /*! We only return an actual mutex if we were passed
00143       ALLOW_ONLINE_CHANGES in our constructor (i.e.,
00144       ModelParamBase::allowsOnlineChanges() returns true); that's
00145       because we assume that if online parameter changes are disabled,
00146       then there is no need for between-thread synchronization of our
00147       parameter value.
00148 
00149       The returned mutex, if non-null, will be an error-checking mutex
00150       so that we can detect attempts to acquire the lock more than
00151       once from within the same thread. These attempts would represent
00152       reentrant setVal() calls, such as when setVal() triggers a
00153       paramChanged() call that in turn triggers another setVal() of
00154       the same parameter (which is forbidden by design).
00155   */
00156   pthread_mutex_t* writeLock() const
00157   { return itsLocks ? &itsLocks[WRITELOCK] : 0; }
00158 
00159 private:
00160   // Yes, there is no parameter value data proper and no way to get
00161   // the parameter value directly! This is only a helper class. The
00162   // NModelParam and OModelParam classes provide concrete paramter
00163   // values.
00164 
00165   //! indices into the optional 2-element itsLocks array
00166   enum { READLOCK = 0, WRITELOCK = 1 };
00167 
00168   ModelParamBase*       const itsSelf;   //!< our owner
00169   ParamClient*          const itsClient; //!< keep track of our client
00170   ModelOptionDef const* const itsOption; //!< may be null
00171   std::string           const itsName;   //!< the parameter name as used in ParamMap
00172   pthread_mutex_t*      const itsLocks;  //!< optional 2-element array of {read,write} locks for getVal()/setVal()
00173   bool                        itsInCallback; //!< whether we're currently doing a paramChanged() callback
00174 
00175   ModelParamAuxImpl(const ModelParamAuxImpl& m);      //!< forbid copy-contruction
00176   ModelParamAuxImpl& operator=(const ModelParamAuxImpl& m); //!< forbid copy
00177 };
00178 
00179 // ######################################################################
00180 //! Helper class to provide transactional semantics for a value change
00181 /*! The provisionally assigns a new value to a variable, but upon
00182     destruction (e.g. at block exit), the original value is restored
00183     unless the transaction has been explicitly accepted. */
00184 template <class T>
00185 class ValueChangeTransaction
00186 {
00187 public:
00188   ValueChangeTransaction(T* p, const T& newval)
00189     : oldval(*p), var(p), accepted(false)
00190   {
00191     *var = newval;
00192   }
00193 
00194   ~ValueChangeTransaction()
00195   {
00196     if (!accepted)
00197       // Note, if this destructor is triggered because of exception
00198       // propagation, and the *var=oldval assignment also causes an
00199       // exception, then we will crash with std::terminate(). In
00200       // practice, this shouldn't be much of a problem since
00201       // operator=() should generally be exception-free for the kinds
00202       // of types that are held in model params.
00203       *var = oldval;
00204   }
00205 
00206   void acceptChange() { accepted = true; }
00207 
00208 private:
00209   T const oldval;
00210   T* const var;
00211   bool accepted;
00212 };
00213 
00214 // ######################################################################
00215 //! A class for params of type T that don't have command-line options
00216 /*! NModelParam delegates its implementation to
00217     ModelParamAuxImpl. NModelParam<T> offers getVal() and setVal() for
00218     direct access to the T value.
00219 
00220     Note that the implementation is entirely inline so that we don't
00221     have to explicitly instantiate NModelParam<T> anywhere; plus these
00222     functions are small so any compile time hit from having the
00223     functions inline is small.
00224 
00225     Note that we have two similar template types: NModelParam and
00226     OModelParam. The 'O' is for "command-line Option", and the 'N' is
00227     for "Not a command-line option". NModelParam only implements
00228     ModelParamBase and is constructed with a string for its parameter
00229     name. On the other hand, OModelParam implements
00230     OptionedModelParam, which means that it offers getOptionDef(), and
00231     it takes a ModelOptionDef* in its constructor instead of a string
00232     (the parameter name is taken from the ModelOptionDef).
00233 */
00234 template <class T> class NModelParam : public ModelParamBase
00235 {
00236 public:
00237   // ######################################################################
00238   /*! @name Constructors and Destructors */
00239   //@{
00240 
00241   //! Construct with a string name only
00242   /*! Same as ModelParamAuxImpl plus an initial parameter value
00243 
00244       @param flags If flags contains ALLOW_ONLINE_CHANGES, then this
00245       param will be marked as being able to be changed while the model
00246       is active.
00247   */
00248   inline NModelParam(const std::string& nam, ParamClient* client,
00249                      const T& initval, const ParamFlag flags = 0);
00250 
00251   //! A "pseudo-constructor" that makes a rutz::shared_ptr<NModelParam>.
00252   /*! This can be used in places that need arrays of NModelParam
00253       objects. Since NModelParam doesn't have a default constructor, we
00254       can't make an array of NModelParam objects. But we can make an
00255       array of rutz::shared_ptr<NModelParam> objects. Then we can initialize
00256       each in a loop by doing arr[i] = NModelParam<T>::make(...).
00257 
00258       Note that an alternative to C-style arrays (where the type must
00259       have a default constructor) is to use std::vector. Then we can
00260       do vec.push_back(NModelParam<T>(...)) and build the vector
00261       incrementally, again without needed a default constructor.
00262 
00263       Historical note: this substitutes for the previous strategy of
00264       giving NModelParam a default constructor plus an init() method
00265       that would be called in the array-initialization loop like
00266       arr[i].init(...), plus an initialized() methed. The current
00267       approach avoids the need for either init() or initialized(),
00268       instead we can let rutz::shared_ptr worry about whether the object is
00269       initialized -- we can test rutz::shared_ptr<NModelParam<T>>::get() != 0
00270       to see if the param is initialized.
00271   */
00272   static inline rutz::shared_ptr<NModelParam<T> >
00273   make(const std::string& nam, ParamClient* client, const T& initval,
00274        const ParamFlag flags = 0)
00275   { return rutz::shared_ptr<NModelParam<T> >(new NModelParam<T>(nam, client, initval, flags)); }
00276 
00277   //@}
00278 
00279   // ######################################################################
00280   /*! @name Access functions */
00281   //@{
00282 
00283   //! get the ModelParamAuxImpl's name
00284   virtual std::string getName() const
00285   { return impl.getName(); }
00286 
00287   //! Get the value
00288   /*! Note that there is no non-const function to get a non-const
00289       reference; that's because if we handed out a non-const reference
00290       then we'd have no way to know if callers changed the value, and
00291       we wouldn't be able to properly trigger paramChanged() on our
00292       ParamClient. Thus if you need to change the value, you should
00293       call getVal() to get a copy of the value, then do your
00294       modifications, then apply those changes with setVal(), which
00295       will trigger a paramChanged(). */
00296   T getVal() const
00297   {
00298     GVX_MUTEX_LOCK(impl.readLock());
00299     return this->val;
00300   }
00301 
00302   //! Set the value
00303   /*! @return true if the change succeeded; false otherwise. */
00304   bool setVal(const T& v)
00305   {
00306     // acquire a write lock for the entire duration of the setVal()
00307     // call, so that no other clients can enter setVal() concurrently;
00308     // in addition, since the write lock is an error-checking mutex,
00309     // we will get an error if setVal() is called recursively from
00310     // within the same thread such that a deadlock would otherwise
00311     // occur
00312     GVX_MUTEX_LOCK(impl.writeLock());
00313 
00314     // acquire a read lock to block out readers in other threads while
00315     // we update this->val (this is a recursive lock so we only block
00316     // out other threads but don't block ourselves from calling
00317     // getVal() from within the sendChangedMessage() call):
00318     GVX_MUTEX_LOCK(impl.readLock());
00319 
00320     const bool didchange = !(this->val == v);
00321     ValueChangeTransaction<T> tx(&this->val, v);
00322 
00323     if (ParamClient::CHANGE_REJECTED
00324         != impl.sendChangedMessage(didchange))
00325       {
00326         tx.acceptChange();
00327         return true;
00328       }
00329     return false;
00330   }
00331 
00332   //! Get the value as a string
00333   virtual std::string getValString() const
00334   {
00335     return convertToString(this->getVal());
00336   }
00337 
00338   //! Set the parameter value from a textual representation, notify clients of the change
00339   /*! @return true if the change succeeded; false otherwise. */
00340   virtual bool setValString(const std::string& textval)
00341   {
00342     T newval;
00343     convertFromString(textval, newval);
00344     // don't update this->val until after we are sure that the
00345     // convertFromString() has succeeded; that way if
00346     // convertFromString() fails we won't end up with a partially
00347     // modified or garbled value in this->val
00348     return this->setVal(newval);
00349   }
00350 
00351   //! Get the current value through a dynamically-typed RefHolder.
00352   inline virtual void getValGeneric(RefHolder& ref) const;
00353 
00354   //! Set the current value through a dynamically-typed RefHolder.
00355   /*! @return true if the change succeeded; false otherwise. */
00356   inline virtual bool setValGeneric(const RefHolder& ref);
00357 
00358   //@}
00359 
00360 
00361   // ######################################################################
00362   /*! @name Input/Output functions */
00363   //@{
00364 
00365   //! Print out our name and contents, mostly for debugging
00366   virtual void printout(std::ostream& s,
00367                         const std::string& prefix = "") const
00368   { impl.printout(s, prefix); }
00369 
00370   //! Write parameter value to ParamMap
00371   virtual void writeTo(ParamMap& pmap) const
00372   { impl.writeTo(pmap); }
00373 
00374   //! Get parameter value from ParamMap
00375   /*! @param noerr will not generate an error message if the parameter
00376     does not exist in ParamMap. */
00377   virtual void readFrom(const ParamMap& pmap,
00378                         const bool noerr = true)
00379   { impl.readFrom(pmap, noerr); }
00380 
00381   //@}
00382 
00383 private:
00384   ModelParamAuxImpl impl;
00385   T val;     // the parameter value
00386   NModelParam(const NModelParam<T>& m);      //!< forbid copy-contruction
00387   NModelParam& operator=(const NModelParam<T>& m); //!< forbid copy
00388 };
00389 
00390 
00391 
00392 // ######################################################################
00393 //! A class for params of type T that have a command-line option
00394 /*! OModelParam is just like NModelParam except that it offers
00395     getOptionDef() and takes a ModelOptionDef* in its constructor. See
00396     the NModelParam documentation for all other details.
00397 */
00398 template <class T> class OModelParam : public OptionedModelParam
00399 {
00400 public:
00401   // ######################################################################
00402   /*! @name Constructors and Destructors
00403 
00404       see NModelParam for more details
00405   */
00406   //@{
00407 
00408   //! Construct, using the initial value from a ModelOptionDef
00409   /*! If you want to specify a different initial value, use the other
00410       constructor which takes an initial value plus a USE_MY_VAL flag.
00411 
00412       @param flags If flags contains ALLOW_ONLINE_CHANGES, then this
00413       param will be marked as being able to be changed while the model
00414       is active.
00415   */
00416   inline OModelParam(const ModelOptionDef* def, ParamClient* client,
00417                      const ParamFlag flags = 0);
00418 
00419   //! Construct, using a specified initial value
00420   /*! @param flags If flags contains USE_MY_VAL, then the given
00421       initval will be pushed into the OptionManager as the new default
00422       value for the given ModelOptionDef. If you just want to take the
00423       existing default value from the ModelOptionDef as the initial
00424       value for this OModelParam, then use the other constructor that
00425       doesn't take an initval parameter. If flags contains
00426       ALLOW_ONLINE_CHANGES, then this param will be marked as being
00427       able to be changed while the model is active. */
00428   inline OModelParam(const ModelOptionDef* def, ParamClient* client,
00429                      const T& initval, const ParamFlag flags);
00430 
00431   //! A "pseudo-constructor" that makes a rutz::shared_ptr<OModelParam>.
00432   static inline rutz::shared_ptr<OModelParam<T> >
00433   make(const ModelOptionDef* def, ParamClient* client,
00434        const ParamFlag flags = 0)
00435   {
00436     return rutz::shared_ptr<OModelParam<T> > (new OModelParam<T>(def, client, flags));
00437   }
00438 
00439   //! A "pseudo-constructor" that makes a rutz::shared_ptr<OModelParam>.
00440   static inline rutz::shared_ptr<OModelParam<T> >
00441   make(const ModelOptionDef* def, ParamClient* client,
00442        const T& initval, const ParamFlag flags)
00443   {
00444     return rutz::shared_ptr<OModelParam<T> >
00445       (new OModelParam<T>(def, client, initval, flags));
00446   }
00447 
00448   //@}
00449 
00450   // ######################################################################
00451   /*! @name Access functions
00452 
00453       see NModelParam for more details
00454   */
00455   //@{
00456 
00457   //! get the ModelParamAuxImpl's name
00458   virtual std::string getName() const
00459   { return impl.getName(); }
00460 
00461   //! get the associated option def
00462   virtual const ModelOptionDef* getOptionDef() const
00463   { return impl.getOptionDef(); }
00464 
00465   //! Get the value
00466   /*! Note that there is no non-const function to get a non-const
00467       reference; that's because if we handed out a non-const reference
00468       then we'd have no way to know if callers changed the value, and
00469       we wouldn't be able to properly trigger paramChanged() on our
00470       ParamClient. Thus if you need to change the value, you should
00471       call getVal() to get a copy of the value, then do your
00472       modifications, then apply those changes with setVal(), which
00473       will trigger a paramChanged(). */
00474   T getVal() const
00475   {
00476     GVX_MUTEX_LOCK(impl.readLock());
00477     return this->val;
00478   }
00479 
00480   //! Set the value
00481   /*! @return true if the change succeeded; false otherwise. */
00482   bool setVal(const T& v)
00483   {
00484     // acquire a write lock for the entire duration of the setVal()
00485     // call, so that no other clients can enter setVal() concurrently;
00486     // in addition, since the write lock is an error-checking mutex,
00487     // we will get an error if setVal() is called recursively from
00488     // within the same thread such that a deadlock would otherwise
00489     // occur
00490     GVX_MUTEX_LOCK(impl.writeLock());
00491 
00492     // acquire a read lock to block out readers in other threads while
00493     // we update this->val (this is a recursive lock so we only block
00494     // out other threads but don't block ourselves from calling
00495     // getVal() from within the sendChangedMessage() call):
00496     GVX_MUTEX_LOCK(impl.readLock());
00497 
00498     const bool didchange = !(this->val == v);
00499     ValueChangeTransaction<T> tx(&this->val, v);
00500 
00501     if (ParamClient::CHANGE_REJECTED
00502         != impl.sendChangedMessage(didchange))
00503       {
00504         tx.acceptChange();
00505         return true;
00506       }
00507     return false;
00508   }
00509 
00510   //! Get the value as a string
00511   virtual std::string getValString() const
00512   {
00513     return convertToString(this->getVal());
00514   }
00515 
00516   //! Set the parameter value from a textual representation, notify clients of the change
00517   /*! @return true if the change succeeded; false otherwise. */
00518   virtual bool setValString(const std::string& textval)
00519   {
00520     T newval;
00521     convertFromString(textval, newval);
00522     // don't update this->val until after we are sure that the
00523     // convertFromString() has succeeded; that way if
00524     // convertFromString() fails we won't end up with a partially
00525     // modified or garbled value in this->val
00526     return this->setVal(newval);
00527   }
00528 
00529   //! Get the current value through a dynamically-typed RefHolder.
00530   inline virtual void getValGeneric(RefHolder& ref) const;
00531 
00532   //! Set the current value through a dynamically-typed RefHolder.
00533   /*! @return true if the change succeeded; false otherwise. */
00534   inline virtual bool setValGeneric(const RefHolder& ref);
00535 
00536   //@}
00537 
00538 
00539   // ######################################################################
00540   /*! @name Input/Output functions
00541 
00542       see NModelParam for more details
00543   */
00544   //@{
00545 
00546   //! Print out our name and contents, mostly for debugging
00547   virtual void printout(std::ostream& s,
00548                         const std::string& prefix = "") const
00549   { impl.printout(s, prefix); }
00550 
00551   //! Write parameter value to ParamMap
00552   virtual void writeTo(ParamMap& pmap) const
00553   { impl.writeTo(pmap); }
00554 
00555   //! Get parameter value from ParamMap
00556   virtual void readFrom(const ParamMap& pmap,
00557                         const bool noerr = true)
00558   { impl.readFrom(pmap, noerr); }
00559 
00560   //@}
00561 
00562 private:
00563   ModelParamAuxImpl impl;
00564   T val;     // the parameter value
00565   OModelParam(const OModelParam<T>& m);      //!< forbid copy-contruction
00566   OModelParam& operator=(const OModelParam<T>& m); //!< forbid copy
00567 };
00568 
00569 
00570 
00571 // ######################################################################
00572 // ############# NModelParam<T> implementation
00573 // ######################################################################
00574 
00575 // ######################################################################
00576 template <class T> inline
00577 NModelParam<T>::NModelParam(const std::string& nam,
00578                             ParamClient* client,
00579                             const T& initval,
00580                             const ParamFlag flags) :
00581   ModelParamBase(flags),
00582   impl(this, nam, client),
00583   val(initval)
00584 {}
00585 
00586 // ######################################################################
00587 template <class T> inline
00588 void NModelParam<T>::getValGeneric(RefHolder& ref) const
00589 {
00590   typedef TRefHolder<T> reftype;
00591   reftype* tref = dynamic_cast<reftype*>(&ref);
00592   if (tref == 0)
00593     rutz::throw_bad_cast(typeid(T), ref.type(), SRC_POS);
00594   tref->ref = this->getVal();
00595 }
00596 
00597 // ######################################################################
00598 template <class T> inline
00599 bool NModelParam<T>::setValGeneric(const RefHolder& ref)
00600 {
00601   typedef TRefHolder<const T> reftype;
00602   const reftype* tref = dynamic_cast<const reftype*>(&ref);
00603   if (tref == 0)
00604     rutz::throw_bad_cast(typeid(T), ref.type(), SRC_POS);
00605   return this->setVal(tref->ref);
00606 }
00607 
00608 
00609 // ######################################################################
00610 // ############# OModelParam<T> implementation
00611 // ######################################################################
00612 
00613 // ######################################################################
00614 template <class T> inline
00615 OModelParam<T>::OModelParam(const ModelOptionDef* def,
00616                             ParamClient* client,
00617                             const ParamFlag flags) :
00618   OptionedModelParam(flags),
00619   impl(this, def, client, /*flags*/ 0, typeid(T)),
00620   val(fromStr<T>(ModelParamAuxImpl::defaultValueOf(def)))
00621 {}
00622 
00623 // ######################################################################
00624 template <class T> inline
00625 OModelParam<T>::OModelParam(const ModelOptionDef* def,
00626                             ParamClient* client,
00627                             const T& initval,
00628                             const int flags) :
00629   OptionedModelParam(flags),
00630   impl(this, def, client, flags, typeid(T)),
00631   val(initval)
00632 {}
00633 
00634 // ######################################################################
00635 template <class T> inline
00636 void OModelParam<T>::getValGeneric(RefHolder& ref) const
00637 {
00638   typedef TRefHolder<T> reftype;
00639   reftype* tref = dynamic_cast<reftype*>(&ref);
00640   if (tref == 0)
00641     rutz::throw_bad_cast(typeid(T), ref.type(), SRC_POS);
00642   tref->ref = this->getVal();
00643 }
00644 
00645 // ######################################################################
00646 template <class T> inline
00647 bool OModelParam<T>::setValGeneric(const RefHolder& ref)
00648 {
00649   typedef TRefHolder<const T> reftype;
00650   const reftype* tref = dynamic_cast<const reftype*>(&ref);
00651   if (tref == 0)
00652     rutz::throw_bad_cast(typeid(T), ref.type(), SRC_POS);
00653   return this->setVal(tref->ref);
00654 }
00655 
00656 #endif
00657 
00658 // ######################################################################
00659 /* So things look consistent in everyone's emacs... */
00660 /* Local Variables: */
00661 /* indent-tabs-mode: nil */
00662 /* End: */
Generated on Sun May 8 08:40:23 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3