Main MRPT website > C++ reference
MRPT logo
metaprogramming.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | The Mobile Robot Programming Toolkit (MRPT) C++ library |
3  | |
4  | http://www.mrpt.org/ |
5  | |
6  | Copyright (C) 2005-2012 University of Malaga |
7  | |
8  | This software was written by the Machine Perception and Intelligent |
9  | Robotics Lab, University of Malaga (Spain). |
10  | Contact: Jose-Luis Blanco <jlblanco@ctima.uma.es> |
11  | |
12  | This file is part of the MRPT project. |
13  | |
14  | MRPT is free software: you can redistribute it and/or modify |
15  | it under the terms of the GNU General Public License as published by |
16  | the Free Software Foundation, either version 3 of the License, or |
17  | (at your option) any later version. |
18  | |
19  | MRPT is distributed in the hope that it will be useful, |
20  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
21  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22  | GNU General Public License for more details. |
23  | |
24  | You should have received a copy of the GNU General Public License |
25  | along with MRPT. If not, see <http://www.gnu.org/licenses/>. |
26  | |
27  +---------------------------------------------------------------------------+ */
28 #ifndef metaprogramming_H
29 #define metaprogramming_H
30 
32 
33 namespace mrpt
34 {
35  namespace utils
36  {
37  /** A set of utility objects for metaprogramming with STL algorithms.
38  * \ingroup stlext_grp
39  */
40  namespace metaprogramming
41  {
42  /** \addtogroup stlext_grp
43  * @{ */
44 
45  /** An object for deleting pointers (intended for STL algorithms) */
46  struct ObjectDelete {
47  template<typename T>
48  inline void operator()(const T *ptr) {
49  delete ptr;
50  }
51  };
52 
53  /** A function which deletes a container of pointers. */
54  template<typename T> inline void DeleteContainer(T &container) {
55  for_each(container.begin(),container.end(),ObjectDelete());
56  }
57 
58  //NOTE: when using this algorithm with for_each, replace the whole line with:
59  // for_each(bypassPointer(<beginning iterator>),bypassPointer(<ending iterator>),mem_fun_ref(&<NonPointerBaseClass>::clear)).
60  /** An object for clearing an object (invokes its method "->clear()") given a pointer or smart-pointer, intended for being used in STL algorithms. */
61  struct ObjectClear {
62  template<typename T>
63  inline void operator()(T &ptr) {
64  if (ptr) ptr->clear();
65  }
66  };
67 
68  //NOTE: replace this with mem_fun_ref(&<BaseClass>::clear).
69  /** An object for clearing an object (invokes its method ".clear()") given a pointer or smart-pointer, intended for being used in STL algorithms. */
70  struct ObjectClear2 {
71  template<typename T>
72  inline void operator()(T &ptr){
73  ptr.clear();
74  }
75  };
76 
77  /** An object for clearing an object->second (invokes its method "clear()") given a pointer or smart-pointer, intended for being used in STL algorithms. */
79  template<typename T>
80  inline void operator()(T obj) {
81  obj.second.clear();
82  }
83  };
84 
85  /** An object for transforming between types/classes, intended for being used in STL algorithms.
86  * Example of usage:
87  * \code
88  * vector_int v1(10); // Input
89  * vector_double v2(10); // Output
90  * std::transform(v1.begin(),v1.end(), v2.begin(), ObjectConvert<double> );
91  * \endcode
92  */
93  template <typename TARGET_TYPE>
94  struct ObjectConvert {
95  template<typename T>
96  inline TARGET_TYPE operator()(const T &val) {
97  return TARGET_TYPE(val);
98  }
99  };
100 
101  //NOTE: replace with mem_fun_ref(&CSerializable::make_unique)
102  /** An object for making smart pointers unique (ie, making copies if necessary), intended for being used in STL algorithms. */
105  typedef void result_type;
107  ptr.make_unique();
108  }
109  };
110 
111  /** An object for making smart pointers unique (ie, making copies if necessary), intended for being used in STL algorithms. */
113  template <typename T>
114  inline void operator()(T &ptr) {
115  ptr.first.make_unique();
116  ptr.second.make_unique();
117  }
118  };
119 
120  //NOTE: replace with mem_fun_ref(&CSerializable::clear_unique)
121  /** An object for making smart pointers unique (ie, making copies if necessary), intended for being used in STL algorithms. */
124  typedef void result_type;
126  {
127  ptr.clear_unique();
128  }
129  };
130 
131  /** An object for reading objects from a stream, intended for being used in STL algorithms. */
133  {
134  private:
136  public:
137  inline ObjectReadFromStream(CStream *stream) : m_stream(stream) { }
138 
139  // T can be CSerializablePtr, CSerializable, or any other class implementing ">>"
140  template <typename T>
141  inline void operator()(T &obj)
142  {
143  (*m_stream) >> obj;
144  }
145  };
146 
147  /** An object for writing objects to a stream, intended for being used in STL algorithms. */
149  {
150  private:
152  public:
153  inline ObjectWriteToStream(CStream *stream) : m_stream(stream) { }
154 
155  // T can be CSerializablePtr, CSerializable, or any other class implementing "<<"
156  template <typename T>
157  inline void operator()(const T &ptr)
158  {
159  (*m_stream) << ptr;
160  }
161  };
162 
163  /** Behaves like std::copy but allows the source and target iterators to be of different types through static typecasting.
164  * \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.
165  * \sa copy_container_typecasting
166  */
167  template<typename it_src, typename it_dst>
168  inline void copy_typecasting(it_src first, it_src last,it_dst target)
169  {
170  for (it_src i=first; i!=last ; ++i,++target)
171  *target = static_cast<typename it_dst::value_type>(*i);
172  }
173 
174  /** Copy all the elements in a container (vector, deque, list) into a different one performing the appropriate typecasting.
175  * The target container is automatically resized to the appropriate size, and previous contents are lost.
176  * This can be used to assign std::vector's of different types:
177  * \code
178  * std::vector<int> vi(10);
179  * std::vector<float> vf;
180  * vf = vi; // Compiler error
181  * mrpt::utils::metaprogramming::copy_container_typecasting(v1,vf); // Ok
182  * \endcode
183  */
184  template<typename src_container, typename dst_container>
185  inline void copy_container_typecasting(const src_container &src, dst_container &trg)
186  {
187  trg.resize( src.size() );
188  typename src_container::const_iterator i = src.begin();
189  typename src_container::const_iterator last = src.end();
190  typename dst_container::iterator target = trg.begin();
191  for ( ; i!=last ; ++i,++target)
192  *target = static_cast<typename dst_container::value_type>(*i);
193  }
194 
195  /** This class bypasses pointer access in iterators to pointers, thus allowing
196  * the use of algorithms that expect an object of class T with containers of T*.
197  * Although it may be used directly, use the bypassPointer function for better
198  * results and readability (since it most probably won't require template
199  * arguments).
200  */
201  template<typename T,typename U> class MemoryBypasserIterator {
202  private:
204  public:
205  typedef typename T::iterator_category iterator_category;
206  typedef U value_type;
207  typedef typename T::difference_type difference_type;
208  typedef U *pointer;
209  typedef U &reference;
210  inline MemoryBypasserIterator(const T &bi):baseIterator(bi) {}
211  inline reference operator*() {
212  return *(*baseIterator);
213  }
215  ++baseIterator;
216  return *this;
217  }
219  MemoryBypasserIterator it=*this;
220  ++baseIterator;
221  return it;
222  }
224  --baseIterator;
225  return *this;
226  }
228  MemoryBypasserIterator it=*this;
229  --baseIterator;
230  return *this;
231  }
233  baseIterator+=off;
234  return *this;
235  }
237  return (MemoryBypasserIterator<T,U>(*this))+=off;
238  }
240  baseIterator-=off;
241  return *this;
242  }
244  return (MemoryBypasserIterator<T,U>(*this))-=off;
245  }
247  return baseIterator-it.baseIterator;
248  }
250  return *(this+off);
251  }
252  inline bool operator==(const MemoryBypasserIterator<T,U> &i) const {
253  return baseIterator==i.baseIterator;
254  }
255  inline bool operator!=(const MemoryBypasserIterator<T,U> &i) const {
256  return baseIterator!=i.baseIterator;
257  }
258  inline bool operator<(const MemoryBypasserIterator<T,U> &i) const {
259  return baseIterator<i.baseIterator;
260  }
261  };
262 
263  /** Sintactic sugar for MemoryBypasserIterator.
264  * For example, having the following declarations:
265  * vector<double *> vec;
266  * void modifyVal(double &v);
267  * The following sentence is not legal:
268  * for_each(vec.begin(),vec.end(),&modifyVal)
269  * But this one is:
270  * for_each(bypassPointer(vec.begin()),bypassPointer(vec.end()),&modifyVal)
271  */
272  template<typename U,typename T> inline MemoryBypasserIterator<T,U> bypassPointer(const T &baseIterator) {
273  return MemoryBypasserIterator<T,U>(baseIterator);
274  }
275 
276  /** This template encapsulates a binary member function and a single object into a
277  * function expecting the two parameters of the member function.
278  * Don't use directly. Use the wrapMember function instead to avoid explicit
279  * template instantiation.
280  */
281  template<typename T,typename U1,typename U2,typename V> class BinaryMemberFunctionWrapper {
282  private:
283  typedef T (V::*MemberFunction)(U1,U2);
284  V &obj;
286  public:
289  typedef T result_type;
291  inline T operator()(U1 p1,U2 p2) {
292  return (obj.*func)(p1,p2);
293  }
294  };
295  /** This template encapsulates an unary member function and a single object into a
296  * function expecting the parameter of the member function.
297  * Don't use directly. Use the wrapMember function instead.
298  */
299  template<typename T,typename U,typename V> class UnaryMemberFunctionWrapper {
300  private:
301  typedef T (V::*MemberFunction)(U);
302  V &obj;
304  public:
305  typedef U argument_type;
306  typedef T result_type;
308  inline T operator()(U p) {
309  return (obj.*func)(p);
310  }
311  };
312  /** This template encapsulates a member function without arguments and a single
313  * object into a function.
314  * Don't use directly. Use the wrapMember function instead.
315  */
316  template<typename T,typename V> class MemberFunctionWrapper {
317  private:
318  typedef T (V::*MemberFunction)(void);
319  V &obj;
321  public:
323  inline T operator()() {
324  return (obj.*func)();
325  }
326  };
327  /** This function creates a function from an object and a member function.
328  * It has three overloads, for zero, one and two parameters in the function.
329  */
330  template<typename T,typename U1,typename U2,typename V> inline BinaryMemberFunctionWrapper<T,U1,U2,V> wrapMember(V &obj,T (V::*fun)(U1,U2)) {
332  }
333  template<typename T,typename U,typename V> inline UnaryMemberFunctionWrapper<T,U,V> wrapMember(V &obj,T (V::*fun)(U)) {
334  return UnaryMemberFunctionWrapper<T,U,V>(obj,fun);
335  }
336  template<typename T,typename V> inline MemberFunctionWrapper<T,V> wrapMember(V &obj,T (V::*fun)(void)) {
337  return MemberFunctionWrapper<T,V>(obj,fun);
338  }
339 
340  /** Equivalent of std::bind1st for functions with non-const arguments.
341  */
342  template<typename Op> class NonConstBind1st {
343  private:
344  Op &op;
345  typename Op::first_argument_type &val;
346  public:
347  typedef typename Op::second_argument_type argument_type;
348  typedef typename Op::result_type result_type;
349  NonConstBind1st(Op &o,typename Op::first_argument_type &t):op(o),val(t) {}
351  return op(val,s);
352  }
353  };
354  /** Use this function instead of directly calling NonConstBind1st.
355  */
356  template<typename Op> inline NonConstBind1st<Op> nonConstBind1st(Op &o,typename Op::first_argument_type &t) {
357  return NonConstBind1st<Op>(o,t);
358  }
359  /** Equivalent of std::bind2nd for functions with non-const arguments.
360  */
361  template<typename Op> class NonConstBind2nd {
362  private:
363  Op &op;
364  typename Op::second_argument_type &val;
365  public:
366  typedef typename Op::first_argument_type argument_type;
367  typedef typename Op::result_type result_type;
368  NonConstBind2nd(Op &o,typename Op::second_argument_type &t):op(o),val(t) {}
370  return op(f,val);
371  }
372  };
373  /** Do not directly use the NonConstBind2nd class directly. Use this function.
374  */
375  template<typename Op> inline NonConstBind2nd<Op> nonConstBind2nd(Op &o,typename Op::second_argument_type &t) {
376  return NonConstBind2nd<Op>(o,t);
377  }
378 
379  /** @} */ // end of grouping
380 
381  } // end metaprogramming
382  } // End of namespace
383 } // end of namespace
384 #endif



Page generated by Doxygen 1.8.3 for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013