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://mrpt.sourceforge.net/                            |
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                   */
00039                 namespace metaprogramming
00040                 {
00041                         /** An object for deleting pointers (intended for STL algorithms) */
00042                         struct ObjectDelete {
00043                                 template<typename T>
00044                                 inline void operator()(const T *ptr) {
00045                                         delete ptr;
00046                                 }
00047                         };
00048 
00049                         /** A function which deletes a container of pointers. */
00050                         template<typename T> inline void DeleteContainer(T &container)  {
00051                                 for_each(container.begin(),container.end(),ObjectDelete());
00052                         }
00053 
00054                         //NOTE: when using this algorithm with for_each, replace the whole line with:
00055                         //      for_each(bypassPointer(<beginning iterator>),bypassPointer(<ending iterator>),mem_fun_ref(&<NonPointerBaseClass>::clear)).
00056                         /** An object for clearing an object (invokes its method "->clear()") given a pointer or smart-pointer, intended for being used in STL algorithms. */
00057                         struct ObjectClear {
00058                                 template<typename T>
00059                                 inline void operator()(T &ptr) {
00060                                         ptr->clear();
00061                                 }
00062                         };
00063 
00064                         //NOTE: replace this with mem_fun_ref(&<BaseClass>::clear).
00065                         /** An object for clearing an object (invokes its method ".clear()") given a pointer or smart-pointer, intended for being used in STL algorithms. */
00066                         struct ObjectClear2 {
00067                                 template<typename T>
00068                                 inline void operator()(T &ptr){
00069                                         ptr.clear();
00070                                 }
00071                         };
00072 
00073                         /** An object for clearing an object->second (invokes its method "clear()") given a pointer or smart-pointer, intended for being used in STL algorithms. */
00074                         struct ObjectClearSecond {
00075                                 template<typename T>
00076                                 inline void operator()(T obj) {
00077                                         obj.second.clear();
00078                                 }
00079                         };
00080 
00081                         /** An object for transforming between types/classes, intended for being used in STL algorithms.
00082                           *  Example of usage:
00083                           *   \code
00084                           *     vector_int      v1(10);  // Input
00085                           *     vector_double   v2(10);  // Output
00086                           *     std::transform(v1.begin(),v1.end(), v2.begin(), ObjectConvert<double> );
00087                           *   \endcode
00088                           */
00089                         template <typename TARGET_TYPE>
00090                         struct ObjectConvert {
00091                                 template<typename T>
00092                                 inline TARGET_TYPE operator()(const T &val) {
00093                                         return TARGET_TYPE(val);
00094                                 }
00095                         };
00096 
00097                         //NOTE: replace with mem_fun_ref(&CSerializable::make_unique)
00098                         /** An object for making smart pointers unique (ie, making copies if necessary), intended for being used in STL algorithms. */
00099                         struct ObjectMakeUnique {
00100                                 typedef mrpt::utils::CObjectPtr argument_type;
00101                                 typedef void result_type;
00102                                 inline void operator()(mrpt::utils::CObjectPtr &ptr) {
00103                                         ptr.make_unique();
00104                                 }
00105                         };
00106 
00107                         /** An object for making smart pointers unique (ie, making copies if necessary), intended for being used in STL algorithms. */
00108                         struct ObjectPairMakeUnique {
00109                                 template <typename T>
00110                                 inline void operator()(T &ptr) {
00111                                         ptr.first.make_unique();
00112                                         ptr.second.make_unique();
00113                                 }
00114                         };
00115 
00116                         //NOTE: replace with mem_fun_ref(&CSerializable::clear_unique)
00117                         /** An object for making smart pointers unique (ie, making copies if necessary), intended for being used in STL algorithms. */
00118                         struct ObjectClearUnique {
00119                                 typedef mrpt::utils::CObjectPtr argument_type;
00120                                 typedef void result_type;
00121                                 inline void operator()(mrpt::utils::CObjectPtr &ptr)
00122                                 {
00123                                         ptr.clear_unique();
00124                                 }
00125                         };
00126 
00127                         /** An object for reading objects from a stream, intended for being used in STL algorithms. */
00128                         struct ObjectReadFromStream
00129                         {
00130                         private:
00131                                 CStream         *m_stream;
00132                         public:
00133                                 inline ObjectReadFromStream(CStream *stream) : m_stream(stream) {  }
00134 
00135                                 // T can be CSerializablePtr, CSerializable, or any other class implementing ">>"
00136                                 template <typename T>
00137                                 inline void operator()(T &obj)
00138                                 {
00139                                         (*m_stream) >> obj;
00140                                 }
00141                         };
00142 
00143                         /** An object for writing objects to a stream, intended for being used in STL algorithms. */
00144                         struct ObjectWriteToStream
00145                         {
00146                         private:
00147                                 CStream         *m_stream;
00148                         public:
00149                                 inline ObjectWriteToStream(CStream *stream) : m_stream(stream) {  }
00150 
00151                                 // T can be CSerializablePtr, CSerializable, or any other class implementing "<<"
00152                                 template <typename T>
00153                                 inline void operator()(const T &ptr)
00154                                 {
00155                                         (*m_stream) << ptr;
00156                                 }
00157                         };
00158 
00159                         /** Behaves like std::copy but allows the source and target iterators to be of different types through static typecasting.
00160                           * \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.
00161                           * \sa copy_container_typecasting
00162                           */
00163                         template<typename it_src, typename it_dst>
00164                         inline void copy_typecasting(it_src  first, it_src last,it_dst  target)
00165                         {
00166                                 for (it_src i=first; i!=last ; ++i,++target)
00167                                         *target = static_cast<typename it_dst::value_type>(*i);
00168                         }
00169 
00170                         /** Copy all the elements in a container (vector, deque, list) into a different one performing the appropriate typecasting.
00171                           *  The target container is automatically resized to the appropriate size, and previous contents are lost.
00172                           *  This can be used to assign std::vector's of different types:
00173                           * \code
00174                           *   std::vector<int>    vi(10);
00175                           *   std::vector<float>  vf;
00176                           *   vf = vi;   // Compiler error
00177                           *   mrpt::utils::metaprogramming::copy_container_typecasting(v1,vf);  // Ok
00178                           * \endcode
00179                           */
00180                         template<typename src_container, typename dst_container>
00181                         inline void copy_container_typecasting(const src_container &src, dst_container &trg)
00182                         {
00183                                 trg.resize( src.size() );
00184                                 typename src_container::const_iterator i = src.begin();
00185                                 typename src_container::const_iterator last = src.end();
00186                                 typename dst_container::iterator target = trg.begin();
00187                                 for ( ; i!=last ; ++i,++target)
00188                                         *target = static_cast<typename dst_container::value_type>(*i);
00189                         }
00190 
00191                         /** This class bypasses pointer access in iterators to pointers, thus allowing
00192                           * the use of algorithms that expect an object of class T with containers of T*.
00193                           * Although it may be used directly, use the bypassPointer function for better
00194                           * results and readability (since it most probably won't require template
00195                           * arguments).
00196                           */
00197                         template<typename T,typename U> class MemoryBypasserIterator    {
00198                         private:
00199                                 T baseIterator;
00200                         public:
00201                                 typedef typename T::iterator_category iterator_category;
00202                                 typedef U value_type;
00203                                 typedef typename T::difference_type difference_type;
00204                                 typedef U *pointer;
00205                                 typedef U &reference;
00206                                 inline MemoryBypasserIterator(const T &bi):baseIterator(bi)     {}
00207                                 inline reference operator*()    {
00208                                         return *(*baseIterator);
00209                                 }
00210                                 inline MemoryBypasserIterator<T,U> &operator++()        {
00211                                         ++baseIterator;
00212                                         return *this;
00213                                 }
00214                                 inline MemoryBypasserIterator<T,U> operator++(int)      {
00215                                         MemoryBypasserIterator it=*this;
00216                                         ++baseIterator;
00217                                         return it;
00218                                 }
00219                                 inline MemoryBypasserIterator<T,U> &operator--()        {
00220                                         --baseIterator;
00221                                         return *this;
00222                                 }
00223                                 inline MemoryBypasserIterator<T,U> operator--(int)      {
00224                                         MemoryBypasserIterator it=*this;
00225                                         --baseIterator;
00226                                         return *this;
00227                                 }
00228                                 inline MemoryBypasserIterator<T,U> &operator+=(difference_type off)     {
00229                                         baseIterator+=off;
00230                                         return *this;
00231                                 }
00232                                 inline MemoryBypasserIterator<T,U> operator+(difference_type off) const {
00233                                         return (MemoryBypasserIterator<T,U>(*this))+=off;
00234                                 }
00235                                 inline MemoryBypasserIterator<T,U> &operator-=(difference_type off)     {
00236                                         baseIterator-=off;
00237                                         return *this;
00238                                 }
00239                                 inline MemoryBypasserIterator<T,U> operator-(difference_type off) const {
00240                                         return (MemoryBypasserIterator<T,U>(*this))-=off;
00241                                 }
00242                                 inline difference_type operator-(const MemoryBypasserIterator<T,U> &it) const   {
00243                                         return baseIterator-it.baseIterator;
00244                                 }
00245                                 inline reference operator[](difference_type off) const  {
00246                                         return *(this+off);
00247                                 }
00248                                 inline bool operator==(const MemoryBypasserIterator<T,U> &i) const      {
00249                                         return baseIterator==i.baseIterator;
00250                                 }
00251                                 inline bool operator!=(const MemoryBypasserIterator<T,U> &i) const      {
00252                                         return baseIterator!=i.baseIterator;
00253                                 }
00254                                 inline bool operator<(const MemoryBypasserIterator<T,U> &i) const       {
00255                                         return baseIterator<i.baseIterator;
00256                                 }
00257                         };
00258 
00259                         /** Sintactic sugar for MemoryBypasserIterator.
00260                           * For example, having the following declarations:
00261                           *             vector<double *> vec;
00262                           *             void modifyVal(double &v);
00263                           * The following sentence is not legal:
00264                           *             for_each(vec.begin(),vec.end(),&modifyVal)
00265                           * But this one is:
00266                           *             for_each(bypassPointer(vec.begin()),bypassPointer(vec.end()),&modifyVal)
00267                           */
00268                         template<typename U,typename T> inline MemoryBypasserIterator<T,U> bypassPointer(const T &baseIterator) {
00269                                 return MemoryBypasserIterator<T,U>(baseIterator);
00270                         }
00271 
00272                         /** This template encapsulates a binary member function and a single object into a
00273                           * function expecting the two parameters of the member function.
00274                           * Don't use directly. Use the wrapMember function instead to avoid explicit
00275                           * template instantiation.
00276                           */
00277                         template<typename T,typename U1,typename U2,typename V> class BinaryMemberFunctionWrapper       {
00278                         private:
00279                                 typedef T (V::*MemberFunction)(U1,U2);
00280                                 V &obj;
00281                                 MemberFunction func;
00282                         public:
00283                                 typedef U1 first_argument_type;
00284                                 typedef U2 second_argument_type;
00285                                 typedef T result_type;
00286                                 inline BinaryMemberFunctionWrapper(V &o,MemberFunction f):obj(o),func(f)        {}
00287                                 inline T operator()(U1 p1,U2 p2)        {
00288                                         return (obj.*func)(p1,p2);
00289                                 }
00290                         };
00291                         /** This template encapsulates an unary member function and a single object into a
00292                           * function expecting the parameter of the member function.
00293                           * Don't use directly. Use the wrapMember function instead.
00294                           */
00295                         template<typename T,typename U,typename V> class UnaryMemberFunctionWrapper     {
00296                         private:
00297                                 typedef T (V::*MemberFunction)(U);
00298                                 V &obj;
00299                                 MemberFunction func;
00300                         public:
00301                                 typedef U argument_type;
00302                                 typedef T result_type;
00303                                 inline UnaryMemberFunctionWrapper(V &o,MemberFunction f):obj(o),func(f) {}
00304                                 inline T operator()(U p)        {
00305                                         return (obj.*func)(p);
00306                                 }
00307                         };
00308                         /** This template encapsulates a member function without arguments and a single
00309                           * object into a function.
00310                           * Don't use directly. Use the wrapMember function instead.
00311                           */
00312                         template<typename T,typename V> class MemberFunctionWrapper     {
00313                         private:
00314                                 typedef T (V::*MemberFunction)(void);
00315                                 V &obj;
00316                                 MemberFunction func;
00317                         public:
00318                                 inline MemberFunctionWrapper(V &o,MemberFunction f):obj(o),func(f)      {}
00319                                 inline T operator()()   {
00320                                         return (obj.*func)();
00321                                 }
00322                         };
00323                         /** This function creates a function from an object and a member function.
00324                           * It has three overloads, for zero, one and two parameters in the function.
00325                           */
00326                         template<typename T,typename U1,typename U2,typename V> inline BinaryMemberFunctionWrapper<T,U1,U2,V> wrapMember(V &obj,T (V::*fun)(U1,U2))     {
00327                                 return BinaryMemberFunctionWrapper<T,U1,U2,V>(obj,fun);
00328                         }
00329                         template<typename T,typename U,typename V> inline UnaryMemberFunctionWrapper<T,U,V> wrapMember(V &obj,T (V::*fun)(U))   {
00330                                 return UnaryMemberFunctionWrapper<T,U,V>(obj,fun);
00331                         }
00332                         template<typename T,typename V> inline MemberFunctionWrapper<T,V> wrapMember(V &obj,T (V::*fun)(void))  {
00333                                 return MemberFunctionWrapper<T,V>(obj,fun);
00334                         }
00335 
00336                         /** Equivalent of std::bind1st for functions with non-const arguments.
00337                           */
00338                         template<typename Op> class NonConstBind1st     {
00339                         private:
00340                                 Op &op;
00341                                 typename Op::first_argument_type &val;
00342                         public:
00343                                 typedef typename Op::second_argument_type argument_type;
00344                                 typedef typename Op::result_type result_type;
00345                                 NonConstBind1st(Op &o,typename Op::first_argument_type &t):op(o),val(t) {}
00346                                 inline result_type operator()(argument_type &s) {
00347                                         return op(val,s);
00348                                 }
00349                         };
00350                         /** Use this function instead of directly calling NonConstBind1st.
00351                           */
00352                         template<typename Op> inline NonConstBind1st<Op> nonConstBind1st(Op &o,typename Op::first_argument_type &t)     {
00353                                 return NonConstBind1st<Op>(o,t);
00354                         }
00355                         /** Equivalent of std::bind2nd for functions with non-const arguments.
00356                           */
00357                         template<typename Op> class NonConstBind2nd     {
00358                         private:
00359                                 Op &op;
00360                                 typename Op::second_argument_type &val;
00361                         public:
00362                                 typedef typename Op::first_argument_type argument_type;
00363                                 typedef typename Op::result_type result_type;
00364                                 NonConstBind2nd(Op &o,typename Op::second_argument_type &t):op(o),val(t)        {}
00365                                 inline result_type operator()(argument_type &f) {
00366                                         return op(f,val);
00367                                 }
00368                         };
00369                         /** Do not directly use the NonConstBind2nd class directly. Use this function.
00370                           */
00371                         template<typename Op> inline NonConstBind2nd<Op> nonConstBind2nd(Op &o,typename Op::second_argument_type &t)    {
00372                                 return NonConstBind2nd<Op>(o,t);
00373                         }
00374 
00375                 } // end metaprogramming
00376         } // End of namespace
00377 } // end of namespace
00378 #endif



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN:exported at Tue Jan 25 21:56:31 UTC 2011