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