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