Main MRPT website > C++ reference
MRPT logo
metaprogramming.h
Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                       http://www.mrpt.org/                                |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef metaprogramming_H
00029 #define metaprogramming_H
00030 
00031 #include <mrpt/utils/CSerializable.h>
00032 
00033 namespace mrpt
00034 {
00035         namespace utils
00036         {
00037                 /** A set of utility objects for metaprogramming with STL algorithms.
00038                   * \ingroup stlext_grp
00039                   */
00040                 namespace metaprogramming
00041                 {
00042                         /** \addtogroup stlext_grp
00043                           * @{ */
00044 
00045                         /** An object for deleting pointers (intended for STL algorithms) */
00046                         struct ObjectDelete {
00047                                 template<typename T>
00048                                 inline void operator()(const T *ptr) {
00049                                         delete ptr;
00050                                 }
00051                         };
00052 
00053                         /** A function which deletes a container of pointers. */
00054                         template<typename T> inline void DeleteContainer(T &container)  {
00055                                 for_each(container.begin(),container.end(),ObjectDelete());
00056                         }
00057 
00058                         //NOTE: when using this algorithm with for_each, replace the whole line with:
00059                         //      for_each(bypassPointer(<beginning iterator>),bypassPointer(<ending iterator>),mem_fun_ref(&<NonPointerBaseClass>::clear)).
00060                         /** An object for clearing an object (invokes its method "->clear()") given a pointer or smart-pointer, intended for being used in STL algorithms. */
00061                         struct ObjectClear {
00062                                 template<typename T>
00063                                 inline void operator()(T &ptr) {
00064                                         if (ptr) ptr->clear();
00065                                 }
00066                         };
00067 
00068                         //NOTE: replace this with mem_fun_ref(&<BaseClass>::clear).
00069                         /** An object for clearing an object (invokes its method ".clear()") given a pointer or smart-pointer, intended for being used in STL algorithms. */
00070                         struct ObjectClear2 {
00071                                 template<typename T>
00072                                 inline void operator()(T &ptr){
00073                                         ptr.clear();
00074                                 }
00075                         };
00076 
00077                         /** An object for clearing an object->second (invokes its method "clear()") given a pointer or smart-pointer, intended for being used in STL algorithms. */
00078                         struct ObjectClearSecond {
00079                                 template<typename T>
00080                                 inline void operator()(T obj) {
00081                                         obj.second.clear();
00082                                 }
00083                         };
00084 
00085                         /** An object for transforming between types/classes, intended for being used in STL algorithms.
00086                           *  Example of usage:
00087                           *   \code
00088                           *     vector_int      v1(10);  // Input
00089                           *     vector_double   v2(10);  // Output
00090                           *     std::transform(v1.begin(),v1.end(), v2.begin(), ObjectConvert<double> );
00091                           *   \endcode
00092                           */
00093                         template <typename TARGET_TYPE>
00094                         struct ObjectConvert {
00095                                 template<typename T>
00096                                 inline TARGET_TYPE operator()(const T &val) {
00097                                         return TARGET_TYPE(val);
00098                                 }
00099                         };
00100 
00101                         //NOTE: replace with mem_fun_ref(&CSerializable::make_unique)
00102                         /** An object for making smart pointers unique (ie, making copies if necessary), intended for being used in STL algorithms. */
00103                         struct ObjectMakeUnique {
00104                                 typedef mrpt::utils::CObjectPtr argument_type;
00105                                 typedef void result_type;
00106                                 inline void operator()(mrpt::utils::CObjectPtr &ptr) {
00107                                         ptr.make_unique();
00108                                 }
00109                         };
00110 
00111                         /** An object for making smart pointers unique (ie, making copies if necessary), intended for being used in STL algorithms. */
00112                         struct ObjectPairMakeUnique {
00113                                 template <typename T>
00114                                 inline void operator()(T &ptr) {
00115                                         ptr.first.make_unique();
00116                                         ptr.second.make_unique();
00117                                 }
00118                         };
00119 
00120                         //NOTE: replace with mem_fun_ref(&CSerializable::clear_unique)
00121                         /** An object for making smart pointers unique (ie, making copies if necessary), intended for being used in STL algorithms. */
00122                         struct ObjectClearUnique {
00123                                 typedef mrpt::utils::CObjectPtr argument_type;
00124                                 typedef void result_type;
00125                                 inline void operator()(mrpt::utils::CObjectPtr &ptr)
00126                                 {
00127                                         ptr.clear_unique();
00128                                 }
00129                         };
00130 
00131                         /** An object for reading objects from a stream, intended for being used in STL algorithms. */
00132                         struct ObjectReadFromStream
00133                         {
00134                         private:
00135                                 CStream         *m_stream;
00136                         public:
00137                                 inline ObjectReadFromStream(CStream *stream) : m_stream(stream) {  }
00138 
00139                                 // T can be CSerializablePtr, CSerializable, or any other class implementing ">>"
00140                                 template <typename T>
00141                                 inline void operator()(T &obj)
00142                                 {
00143                                         (*m_stream) >> obj;
00144                                 }
00145                         };
00146 
00147                         /** An object for writing objects to a stream, intended for being used in STL algorithms. */
00148                         struct ObjectWriteToStream
00149                         {
00150                         private:
00151                                 CStream         *m_stream;
00152                         public:
00153                                 inline ObjectWriteToStream(CStream *stream) : m_stream(stream) {  }
00154 
00155                                 // T can be CSerializablePtr, CSerializable, or any other class implementing "<<"
00156                                 template <typename T>
00157                                 inline void operator()(const T &ptr)
00158                                 {
00159                                         (*m_stream) << ptr;
00160                                 }
00161                         };
00162 
00163                         /** Behaves like std::copy but allows the source and target iterators to be of different types through static typecasting.
00164                           * \note As in std::copy, the target iterator must point to the first "slot" where to put the first transformed element, and sufficient space must be allocated in advance.
00165                           * \sa copy_container_typecasting
00166                           */
00167                         template<typename it_src, typename it_dst>
00168                         inline void copy_typecasting(it_src  first, it_src last,it_dst  target)
00169                         {
00170                                 for (it_src i=first; i!=last ; ++i,++target)
00171                                         *target = static_cast<typename it_dst::value_type>(*i);
00172                         }
00173 
00174                         /** Copy all the elements in a container (vector, deque, list) into a different one performing the appropriate typecasting.
00175                           *  The target container is automatically resized to the appropriate size, and previous contents are lost.
00176                           *  This can be used to assign std::vector's of different types:
00177                           * \code
00178                           *   std::vector<int>    vi(10);
00179                           *   std::vector<float>  vf;
00180                           *   vf = vi;   // Compiler error
00181                           *   mrpt::utils::metaprogramming::copy_container_typecasting(v1,vf);  // Ok
00182                           * \endcode
00183                           */
00184                         template<typename src_container, typename dst_container>
00185                         inline void copy_container_typecasting(const src_container &src, dst_container &trg)
00186                         {
00187                                 trg.resize( src.size() );
00188                                 typename src_container::const_iterator i = src.begin();
00189                                 typename src_container::const_iterator last = src.end();
00190                                 typename dst_container::iterator target = trg.begin();
00191                                 for ( ; i!=last ; ++i,++target)
00192                                         *target = static_cast<typename dst_container::value_type>(*i);
00193                         }
00194 
00195                         /** This class bypasses pointer access in iterators to pointers, thus allowing
00196                           * the use of algorithms that expect an object of class T with containers of T*.
00197                           * Although it may be used directly, use the bypassPointer function for better
00198                           * results and readability (since it most probably won't require template
00199                           * arguments).
00200                           */
00201                         template<typename T,typename U> class MemoryBypasserIterator    {
00202                         private:
00203                                 T baseIterator;
00204                         public:
00205                                 typedef typename T::iterator_category iterator_category;
00206                                 typedef U value_type;
00207                                 typedef typename T::difference_type difference_type;
00208                                 typedef U *pointer;
00209                                 typedef U &reference;
00210                                 inline MemoryBypasserIterator(const T &bi):baseIterator(bi)     {}
00211                                 inline reference operator*()    {
00212                                         return *(*baseIterator);
00213                                 }
00214                                 inline MemoryBypasserIterator<T,U> &operator++()        {
00215                                         ++baseIterator;
00216                                         return *this;
00217                                 }
00218                                 inline MemoryBypasserIterator<T,U> operator++(int)      {
00219                                         MemoryBypasserIterator it=*this;
00220                                         ++baseIterator;
00221                                         return it;
00222                                 }
00223                                 inline MemoryBypasserIterator<T,U> &operator--()        {
00224                                         --baseIterator;
00225                                         return *this;
00226                                 }
00227                                 inline MemoryBypasserIterator<T,U> operator--(int)      {
00228                                         MemoryBypasserIterator it=*this;
00229                                         --baseIterator;
00230                                         return *this;
00231                                 }
00232                                 inline MemoryBypasserIterator<T,U> &operator+=(difference_type off)     {
00233                                         baseIterator+=off;
00234                                         return *this;
00235                                 }
00236                                 inline MemoryBypasserIterator<T,U> operator+(difference_type off) const {
00237                                         return (MemoryBypasserIterator<T,U>(*this))+=off;
00238                                 }
00239                                 inline MemoryBypasserIterator<T,U> &operator-=(difference_type off)     {
00240                                         baseIterator-=off;
00241                                         return *this;
00242                                 }
00243                                 inline MemoryBypasserIterator<T,U> operator-(difference_type off) const {
00244                                         return (MemoryBypasserIterator<T,U>(*this))-=off;
00245                                 }
00246                                 inline difference_type operator-(const MemoryBypasserIterator<T,U> &it) const   {
00247                                         return baseIterator-it.baseIterator;
00248                                 }
00249                                 inline reference operator[](difference_type off) const  {
00250                                         return *(this+off);
00251                                 }
00252                                 inline bool operator==(const MemoryBypasserIterator<T,U> &i) const      {
00253                                         return baseIterator==i.baseIterator;
00254                                 }
00255                                 inline bool operator!=(const MemoryBypasserIterator<T,U> &i) const      {
00256                                         return baseIterator!=i.baseIterator;
00257                                 }
00258                                 inline bool operator<(const MemoryBypasserIterator<T,U> &i) const       {
00259                                         return baseIterator<i.baseIterator;
00260                                 }
00261                         };
00262 
00263                         /** Sintactic sugar for MemoryBypasserIterator.
00264                           * For example, having the following declarations:
00265                           *             vector<double *> vec;
00266                           *             void modifyVal(double &v);
00267                           * The following sentence is not legal:
00268                           *             for_each(vec.begin(),vec.end(),&modifyVal)
00269                           * But this one is:
00270                           *             for_each(bypassPointer(vec.begin()),bypassPointer(vec.end()),&modifyVal)
00271                           */
00272                         template<typename U,typename T> inline MemoryBypasserIterator<T,U> bypassPointer(const T &baseIterator) {
00273                                 return MemoryBypasserIterator<T,U>(baseIterator);
00274                         }
00275 
00276                         /** This template encapsulates a binary member function and a single object into a
00277                           * function expecting the two parameters of the member function.
00278                           * Don't use directly. Use the wrapMember function instead to avoid explicit
00279                           * template instantiation.
00280                           */
00281                         template<typename T,typename U1,typename U2,typename V> class BinaryMemberFunctionWrapper       {
00282                         private:
00283                                 typedef T (V::*MemberFunction)(U1,U2);
00284                                 V &obj;
00285                                 MemberFunction func;
00286                         public:
00287                                 typedef U1 first_argument_type;
00288                                 typedef U2 second_argument_type;
00289                                 typedef T result_type;
00290                                 inline BinaryMemberFunctionWrapper(V &o,MemberFunction f):obj(o),func(f)        {}
00291                                 inline T operator()(U1 p1,U2 p2)        {
00292                                         return (obj.*func)(p1,p2);
00293                                 }
00294                         };
00295                         /** This template encapsulates an unary member function and a single object into a
00296                           * function expecting the parameter of the member function.
00297                           * Don't use directly. Use the wrapMember function instead.
00298                           */
00299                         template<typename T,typename U,typename V> class UnaryMemberFunctionWrapper     {
00300                         private:
00301                                 typedef T (V::*MemberFunction)(U);
00302                                 V &obj;
00303                                 MemberFunction func;
00304                         public:
00305                                 typedef U argument_type;
00306                                 typedef T result_type;
00307                                 inline UnaryMemberFunctionWrapper(V &o,MemberFunction f):obj(o),func(f) {}
00308                                 inline T operator()(U p)        {
00309                                         return (obj.*func)(p);
00310                                 }
00311                         };
00312                         /** This template encapsulates a member function without arguments and a single
00313                           * object into a function.
00314                           * Don't use directly. Use the wrapMember function instead.
00315                           */
00316                         template<typename T,typename V> class MemberFunctionWrapper     {
00317                         private:
00318                                 typedef T (V::*MemberFunction)(void);
00319                                 V &obj;
00320                                 MemberFunction func;
00321                         public:
00322                                 inline MemberFunctionWrapper(V &o,MemberFunction f):obj(o),func(f)      {}
00323                                 inline T operator()()   {
00324                                         return (obj.*func)();
00325                                 }
00326                         };
00327                         /** This function creates a function from an object and a member function.
00328                           * It has three overloads, for zero, one and two parameters in the function.
00329                           */
00330                         template<typename T,typename U1,typename U2,typename V> inline BinaryMemberFunctionWrapper<T,U1,U2,V> wrapMember(V &obj,T (V::*fun)(U1,U2))     {
00331                                 return BinaryMemberFunctionWrapper<T,U1,U2,V>(obj,fun);
00332                         }
00333                         template<typename T,typename U,typename V> inline UnaryMemberFunctionWrapper<T,U,V> wrapMember(V &obj,T (V::*fun)(U))   {
00334                                 return UnaryMemberFunctionWrapper<T,U,V>(obj,fun);
00335                         }
00336                         template<typename T,typename V> inline MemberFunctionWrapper<T,V> wrapMember(V &obj,T (V::*fun)(void))  {
00337                                 return MemberFunctionWrapper<T,V>(obj,fun);
00338                         }
00339 
00340                         /** Equivalent of std::bind1st for functions with non-const arguments.
00341                           */
00342                         template<typename Op> class NonConstBind1st     {
00343                         private:
00344                                 Op &op;
00345                                 typename Op::first_argument_type &val;
00346                         public:
00347                                 typedef typename Op::second_argument_type argument_type;
00348                                 typedef typename Op::result_type result_type;
00349                                 NonConstBind1st(Op &o,typename Op::first_argument_type &t):op(o),val(t) {}
00350                                 inline result_type operator()(argument_type &s) {
00351                                         return op(val,s);
00352                                 }
00353                         };
00354                         /** Use this function instead of directly calling NonConstBind1st.
00355                           */
00356                         template<typename Op> inline NonConstBind1st<Op> nonConstBind1st(Op &o,typename Op::first_argument_type &t)     {
00357                                 return NonConstBind1st<Op>(o,t);
00358                         }
00359                         /** Equivalent of std::bind2nd for functions with non-const arguments.
00360                           */
00361                         template<typename Op> class NonConstBind2nd     {
00362                         private:
00363                                 Op &op;
00364                                 typename Op::second_argument_type &val;
00365                         public:
00366                                 typedef typename Op::first_argument_type argument_type;
00367                                 typedef typename Op::result_type result_type;
00368                                 NonConstBind2nd(Op &o,typename Op::second_argument_type &t):op(o),val(t)        {}
00369                                 inline result_type operator()(argument_type &f) {
00370                                         return op(f,val);
00371                                 }
00372                         };
00373                         /** Do not directly use the NonConstBind2nd class directly. Use this function.
00374                           */
00375                         template<typename Op> inline NonConstBind2nd<Op> nonConstBind2nd(Op &o,typename Op::second_argument_type &t)    {
00376                                 return NonConstBind2nd<Op>(o,t);
00377                         }
00378 
00379                         /** @} */  // end of grouping
00380 
00381                 } // end metaprogramming
00382         } // End of namespace
00383 } // end of namespace
00384 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011