stlab.adobe.com Adobe Systems Incorporated
move.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2005-2007 Adobe Systems Incorporated
3  Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
4  or a copy at http://stlab.adobe.com/licenses.html)
5 */
6 
7 /*************************************************************************************************/
8 
9 #ifndef ADOBE_MOVE_HPP
10 #define ADOBE_MOVE_HPP
11 
12 #include <cassert>
13 #include <iterator>
14 #include <memory>
15 
16 #include <boost/iterator/iterator_adaptor.hpp>
17 #include <boost/mpl/bool.hpp>
18 #include <boost/mpl/and.hpp>
19 #include <boost/mpl/or.hpp>
20 #include <boost/mpl/not.hpp>
21 #include <boost/mpl/assert.hpp>
22 #include <boost/range/begin.hpp>
23 #include <boost/range/end.hpp>
24 #include <boost/type_traits/is_convertible.hpp>
25 #include <boost/type_traits/is_same.hpp>
26 #include <boost/type_traits/is_class.hpp>
27 #include <boost/utility/enable_if.hpp>
28 
247 /*************************************************************************************************/
248 
249 namespace adobe {
250 
251 /*************************************************************************************************/
252 
253 namespace implementation {
254 
255 /*************************************************************************************************/
256 
257 template <typename T>
258 struct class_has_move_assign {
259  class type {
260  typedef T& (T::*E)(T t);
261  typedef char (&no_type)[1];
262  typedef char (&yes_type)[2];
263  template <E e> struct sfinae { typedef yes_type type; };
264  template <class U>
265  static typename sfinae<&U::operator=>::type test(int);
266  template <class U>
267  static no_type test(...);
268  public:
269  enum {value = sizeof(test<T>(1)) == sizeof(yes_type)};
270  };
271  };
272 
273 /*************************************************************************************************/
274 
275 template<typename T>
276 struct has_move_assign : boost::mpl::and_<boost::is_class<T>, class_has_move_assign<T> > {};
277 
278 /*************************************************************************************************/
279 
280 class test_can_convert_anything { };
281 
282 /*************************************************************************************************/
283 
284 } //namespace implementation
285 
286 
287 /*************************************************************************************************/
288 
289 /*
290  REVISIT (sparent@adobe.com): This is a work around for Boost 1.34.1 and VC++ 2008 where
291  boost::is_convertible<T, T> fails to compile.
292 */
293 
294 template <typename T, typename U>
295 struct is_convertible : boost::mpl::or_<
296  boost::is_same<T, U>,
297  boost::is_convertible<T, U>
298 > { };
299 
305 template <typename T>
306 struct move_from
307 {
308  explicit move_from(T& x) : source(x) { }
309  T& source;
310 };
311 
316 template <typename T>
317 struct is_movable : boost::mpl::and_<
318  boost::is_convertible<move_from<T>, T>,
319  implementation::has_move_assign<T>,
320  boost::mpl::not_<boost::is_convertible<implementation::test_can_convert_anything, T> >
321  > { };
322 
323 /*************************************************************************************************/
324 
332 template <typename T,
333  typename U = T,
334  typename R = void*>
335 struct copy_sink : boost::enable_if<
336  boost::mpl::and_<
337  adobe::is_convertible<T, U>,
338  boost::mpl::not_<is_movable<T> >
339  >,
340  R
341  >
342 { };
343 
344 /*************************************************************************************************/
345 
353 template <typename T,
354  typename U = T,
355  typename R = void*>
356 struct move_sink : boost::enable_if<
357  boost::mpl::and_<
358  adobe::is_convertible<T, U>,
359  is_movable<T>
360  >,
361  R
362  >
363 { };
364 
365 /*************************************************************************************************/
366 
374 template <typename T>
375 T move(T& x, typename move_sink<T>::type = 0) { return T(move_from<T>(x)); }
376 
377 /*************************************************************************************************/
378 
384 template <typename T>
385 T& move(T& x, typename copy_sink<T>::type = 0) { return x; }
386 
387 /*************************************************************************************************/
388 
394 template <typename I, // I models InputIterator
395  typename O> // O models OutputIterator
396 O move(I f, I l, O result)
397 {
398  while (f != l) {
399  *result = adobe::move(*f);
400  ++f; ++result;
401  }
402  return result;
403 }
404 
405 /*************************************************************************************************/
406 
412 template <typename I, // I models InputRange
413  typename O> // O models OutputIterator
414 inline O move(I& in, O out) { return adobe::move(boost::begin(in), boost::end(in), out); }
415 
416 /*************************************************************************************************/
417 
423 template <typename I, // I models BidirectionalIterator
424  typename O> // O models BidirectionalIterator
425 O move_backward(I f, I l, O result)
426 {
427  while (f != l) {
428  --l; --result;
429  *result = adobe::move(*l);
430  }
431  return result;
432 }
433 
434 /*************************************************************************************************/
435 
441 template <typename I, // I models BidirectionalRange
442  typename O> // O models BidirectionalIterator
443 inline O move_backward(I& in, O out)
444 { return adobe::move_backward(boost::begin(in), boost::end(in), out); }
445 
446 /*************************************************************************************************/
447 
454 template <typename C> // C models Container
455 class back_move_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void>
456 {
457  C* container_m;
458 
459  public:
460  typedef C container_type;
461 
462  explicit back_move_iterator(C& x) : container_m(&x) { }
463 
464  back_move_iterator& operator=(typename C::value_type x)
465  { container_m->push_back(adobe::move(x)); return *this; }
466 
467  back_move_iterator& operator*() { return *this; }
468  back_move_iterator& operator++() { return *this; }
469  back_move_iterator& operator++(int) { return *this; }
470 };
471 
472 /*************************************************************************************************/
473 
480 template <typename C> // C models Container
482 
483 /*************************************************************************************************/
484 
485 } // namespace adobe
486 
487 /*************************************************************************************************/
488 
489 #endif
490 
491 /*************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google