move_to.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 Joel de Guzman
  3. Copyright (c) 2013 Agustin Berge
  4. http://spirit.sourceforge.net/
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #if !defined(BOOST_SPIRIT_X3_MOVE_TO_JAN_17_2013_0859PM)
  9. #define BOOST_SPIRIT_X3_MOVE_TO_JAN_17_2013_0859PM
  10. #include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
  11. #include <boost/spirit/home/x3/support/traits/tuple_traits.hpp>
  12. #include <boost/spirit/home/x3/support/traits/variant_has_substitute.hpp>
  13. #include <boost/fusion/include/is_sequence.hpp>
  14. #include <boost/fusion/include/front.hpp>
  15. #include <boost/fusion/include/move.hpp>
  16. #include <boost/fusion/include/is_sequence.hpp>
  17. #include <utility>
  18. namespace boost { namespace spirit { namespace x3 { namespace traits
  19. {
  20. template <typename Source, typename Dest>
  21. inline void move_to(Source&& src, Dest& dest);
  22. template <typename T>
  23. inline void move_to(T& src, T& dest);
  24. template <typename T>
  25. inline void move_to(T const& src, T& dest);
  26. template <typename T>
  27. inline void move_to(T&& src, T& dest);
  28. template <typename Iterator, typename Dest>
  29. inline void move_to(Iterator first, Iterator last, Dest& dest);
  30. template <typename Dest>
  31. inline void move_to(unused_type, Dest&) {}
  32. template <typename Source>
  33. inline void move_to(Source&, unused_type) {}
  34. inline void move_to(unused_type, unused_type) {}
  35. template <typename Iterator>
  36. inline void
  37. move_to(Iterator, Iterator, unused_type) {}
  38. namespace detail
  39. {
  40. template <typename Source, typename Dest>
  41. inline void
  42. move_to(Source&&, Dest&, unused_attribute) {}
  43. template <typename Source, typename Dest>
  44. inline void
  45. move_to_plain(Source&& src, Dest& dest, mpl::false_) // src is not a single-element tuple
  46. {
  47. dest = std::move(src);
  48. }
  49. template <typename Source, typename Dest>
  50. inline void
  51. move_to_plain(Source&& src, Dest& dest, mpl::true_) // src is a single-element tuple
  52. {
  53. dest = std::move(fusion::front(src));
  54. }
  55. template <typename Source, typename Dest>
  56. inline void
  57. move_to(Source&& src, Dest& dest, plain_attribute)
  58. {
  59. typename mpl::and_<
  60. fusion::traits::is_sequence<Source>,
  61. is_size_one_sequence<Source> >
  62. is_single_element_sequence;
  63. move_to_plain(std::forward<Source>(src), dest, is_single_element_sequence);
  64. }
  65. template <typename Source, typename Dest>
  66. inline typename enable_if<is_container<Source>>::type
  67. move_to(Source&& src, Dest& dest, container_attribute)
  68. {
  69. traits::move_to(src.begin(), src.end(), dest);
  70. }
  71. template <typename Source, typename Dest>
  72. inline typename enable_if<
  73. mpl::and_<
  74. is_same_size_sequence<Dest, Source>,
  75. mpl::not_<is_size_one_sequence<Dest> > >
  76. >::type
  77. move_to(Source&& src, Dest& dest, tuple_attribute)
  78. {
  79. fusion::move(std::forward<Source>(src), dest);
  80. }
  81. template <typename Source, typename Dest>
  82. inline typename enable_if<
  83. is_size_one_sequence<Dest>
  84. >::type
  85. move_to(Source&& src, Dest& dest, tuple_attribute)
  86. {
  87. traits::move_to(std::forward<Source>(src), fusion::front(dest));
  88. }
  89. template <typename Source, typename Dest>
  90. inline void
  91. move_to(Source&& src, Dest& dest, variant_attribute, mpl::false_)
  92. {
  93. dest = std::move(src);
  94. }
  95. template <typename Source, typename Dest>
  96. inline void
  97. move_to_variant_from_single_element_sequence(Source&& src, Dest& dest, mpl::false_)
  98. {
  99. // dest is a variant, src is a single element fusion sequence that the variant
  100. // cannot directly hold. We'll try to unwrap the single element fusion sequence.
  101. // Make sure that the Dest variant can really hold Source
  102. static_assert(variant_has_substitute<Dest, typename fusion::result_of::front<Source>::type>::value,
  103. "Error! The destination variant (Dest) cannot hold the source type (Source)");
  104. dest = std::move(fusion::front(src));
  105. }
  106. template <typename Source, typename Dest>
  107. inline void
  108. move_to_variant_from_single_element_sequence(Source&& src, Dest& dest, mpl::true_)
  109. {
  110. // dest is a variant, src is a single element fusion sequence that the variant
  111. // *can* directly hold.
  112. dest = std::move(src);
  113. }
  114. template <typename Source, typename Dest>
  115. inline void
  116. move_to(Source&& src, Dest& dest, variant_attribute, mpl::true_)
  117. {
  118. move_to_variant_from_single_element_sequence(src, dest, variant_has_substitute<Dest, Source>());
  119. }
  120. template <typename Source, typename Dest>
  121. inline void
  122. move_to(Source&& src, Dest& dest, variant_attribute tag)
  123. {
  124. move_to(src, dest, tag, is_size_one_sequence<Source>());
  125. }
  126. template <typename Source, typename Dest>
  127. inline void
  128. move_to(Source&& src, Dest& dest, optional_attribute)
  129. {
  130. dest = std::move(src);
  131. }
  132. template <typename Iterator>
  133. inline void
  134. move_to(Iterator, Iterator, unused_type, unused_attribute) {}
  135. template <typename Iterator, typename Dest>
  136. inline void
  137. move_to(Iterator first, Iterator last, Dest& dest, container_attribute)
  138. {
  139. if (is_empty(dest))
  140. dest = Dest(first, last);
  141. else
  142. append(dest, first, last);
  143. }
  144. template <typename Iterator, typename Dest>
  145. inline typename enable_if<
  146. is_size_one_sequence<Dest>
  147. >::type
  148. move_to(Iterator first, Iterator last, Dest& dest, tuple_attribute)
  149. {
  150. traits::move_to(first, last, fusion::front(dest));
  151. }
  152. template <typename Iterator>
  153. inline void
  154. move_to(Iterator first, Iterator last, boost::iterator_range<Iterator>& rng, range_attribute)
  155. {
  156. rng = {first, last};
  157. }
  158. }
  159. template <typename Source, typename Dest>
  160. inline void move_to(boost::optional<Source>&& src, Dest& dest)
  161. {
  162. if (src) detail::move_to(std::move(*src), dest
  163. , typename attribute_category<Dest>::type());
  164. }
  165. template <typename Source, typename Dest>
  166. inline void move_to(Source&& src, Dest& dest)
  167. {
  168. detail::move_to(std::move(src), dest
  169. , typename attribute_category<Dest>::type());
  170. }
  171. template <typename T>
  172. inline void move_to(T& src, T& dest)
  173. {
  174. if (boost::addressof(src) != boost::addressof(dest))
  175. dest = std::move(src);
  176. }
  177. template <typename T>
  178. inline void move_to(T const& src, T& dest)
  179. {
  180. if (boost::addressof(src) != boost::addressof(dest))
  181. dest = std::move(src);
  182. }
  183. template <typename T>
  184. inline void move_to(T&& src, T& dest)
  185. {
  186. if (boost::addressof(src) != boost::addressof(dest))
  187. dest = std::move(src);
  188. }
  189. template <typename Iterator, typename Dest>
  190. inline void move_to(Iterator first, Iterator last, Dest& dest)
  191. {
  192. // $$$ Use std::move_iterator when iterator is not a const-iterator $$$
  193. detail::move_to(first, last, dest, typename attribute_category<Dest>::type());
  194. }
  195. }}}}
  196. #endif