Chris@16
|
1 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 //
|
Chris@101
|
3 // (C) Copyright Ion Gaztanaga 2012-2015.
|
Chris@16
|
4 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
5 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7 //
|
Chris@16
|
8 // See http://www.boost.org/libs/move for documentation.
|
Chris@16
|
9 //
|
Chris@16
|
10 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
11
|
Chris@16
|
12 //! \file
|
Chris@16
|
13
|
Chris@16
|
14 #ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
|
Chris@16
|
15 #define BOOST_MOVE_DETAIL_META_UTILS_HPP
|
Chris@16
|
16
|
Chris@101
|
17 #ifndef BOOST_CONFIG_HPP
|
Chris@101
|
18 # include <boost/config.hpp>
|
Chris@101
|
19 #endif
|
Chris@101
|
20 #
|
Chris@101
|
21 #if defined(BOOST_HAS_PRAGMA_ONCE)
|
Chris@101
|
22 # pragma once
|
Chris@101
|
23 #endif
|
Chris@101
|
24 #include <boost/move/detail/meta_utils_core.hpp>
|
Chris@101
|
25 #include <cstddef> //for std::size_t
|
Chris@16
|
26
|
Chris@16
|
27 //Small meta-typetraits to support move
|
Chris@16
|
28
|
Chris@16
|
29 namespace boost {
|
Chris@101
|
30
|
Chris@101
|
31 //Forward declare boost::rv
|
Chris@101
|
32 template <class T> class rv;
|
Chris@101
|
33
|
Chris@16
|
34 namespace move_detail {
|
Chris@16
|
35
|
Chris@101
|
36 //////////////////////////////////////
|
Chris@101
|
37 // nat
|
Chris@101
|
38 //////////////////////////////////////
|
Chris@101
|
39 struct nat{};
|
Chris@16
|
40
|
Chris@101
|
41 //////////////////////////////////////
|
Chris@101
|
42 // natify
|
Chris@101
|
43 //////////////////////////////////////
|
Chris@101
|
44 template <class T> struct natify{};
|
Chris@16
|
45
|
Chris@101
|
46 //////////////////////////////////////
|
Chris@101
|
47 // remove_reference
|
Chris@101
|
48 //////////////////////////////////////
|
Chris@101
|
49 template<class T>
|
Chris@101
|
50 struct remove_reference
|
Chris@16
|
51 {
|
Chris@16
|
52 typedef T type;
|
Chris@16
|
53 };
|
Chris@16
|
54
|
Chris@101
|
55 template<class T>
|
Chris@101
|
56 struct remove_reference<T&>
|
Chris@16
|
57 {
|
Chris@16
|
58 typedef T type;
|
Chris@16
|
59 };
|
Chris@16
|
60
|
Chris@101
|
61 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
62
|
Chris@101
|
63 template<class T>
|
Chris@101
|
64 struct remove_reference<T&&>
|
Chris@16
|
65 {
|
Chris@101
|
66 typedef T type;
|
Chris@16
|
67 };
|
Chris@16
|
68
|
Chris@101
|
69 #else
|
Chris@16
|
70
|
Chris@101
|
71 template<class T>
|
Chris@101
|
72 struct remove_reference< rv<T> >
|
Chris@101
|
73 {
|
Chris@101
|
74 typedef T type;
|
Chris@101
|
75 };
|
Chris@16
|
76
|
Chris@101
|
77 template<class T>
|
Chris@101
|
78 struct remove_reference< rv<T> &>
|
Chris@101
|
79 {
|
Chris@101
|
80 typedef T type;
|
Chris@101
|
81 };
|
Chris@101
|
82
|
Chris@101
|
83 template<class T>
|
Chris@101
|
84 struct remove_reference< const rv<T> &>
|
Chris@101
|
85 {
|
Chris@101
|
86 typedef T type;
|
Chris@101
|
87 };
|
Chris@101
|
88
|
Chris@101
|
89
|
Chris@101
|
90 #endif
|
Chris@101
|
91
|
Chris@101
|
92 //////////////////////////////////////
|
Chris@101
|
93 // add_const
|
Chris@101
|
94 //////////////////////////////////////
|
Chris@101
|
95 template<class T>
|
Chris@101
|
96 struct add_const
|
Chris@101
|
97 {
|
Chris@101
|
98 typedef const T type;
|
Chris@101
|
99 };
|
Chris@101
|
100
|
Chris@101
|
101 template<class T>
|
Chris@101
|
102 struct add_const<T&>
|
Chris@101
|
103 {
|
Chris@101
|
104 typedef const T& type;
|
Chris@101
|
105 };
|
Chris@101
|
106
|
Chris@101
|
107 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
108
|
Chris@101
|
109 template<class T>
|
Chris@101
|
110 struct add_const<T&&>
|
Chris@101
|
111 {
|
Chris@101
|
112 typedef T&& type;
|
Chris@101
|
113 };
|
Chris@101
|
114
|
Chris@101
|
115 #endif
|
Chris@101
|
116
|
Chris@101
|
117 //////////////////////////////////////
|
Chris@101
|
118 // add_lvalue_reference
|
Chris@101
|
119 //////////////////////////////////////
|
Chris@101
|
120 template<class T>
|
Chris@101
|
121 struct add_lvalue_reference
|
Chris@101
|
122 { typedef T& type; };
|
Chris@101
|
123
|
Chris@101
|
124 template<class T> struct add_lvalue_reference<T&> { typedef T& type; };
|
Chris@101
|
125 template<> struct add_lvalue_reference<void> { typedef void type; };
|
Chris@101
|
126 template<> struct add_lvalue_reference<const void> { typedef const void type; };
|
Chris@101
|
127 template<> struct add_lvalue_reference<volatile void> { typedef volatile void type; };
|
Chris@101
|
128 template<> struct add_lvalue_reference<const volatile void>{ typedef const volatile void type; };
|
Chris@101
|
129
|
Chris@101
|
130 template<class T>
|
Chris@101
|
131 struct add_const_lvalue_reference
|
Chris@101
|
132 {
|
Chris@101
|
133 typedef typename remove_reference<T>::type t_unreferenced;
|
Chris@101
|
134 typedef typename add_const<t_unreferenced>::type t_unreferenced_const;
|
Chris@101
|
135 typedef typename add_lvalue_reference
|
Chris@101
|
136 <t_unreferenced_const>::type type;
|
Chris@101
|
137 };
|
Chris@101
|
138
|
Chris@101
|
139 //////////////////////////////////////
|
Chris@101
|
140 // is_lvalue_reference
|
Chris@101
|
141 //////////////////////////////////////
|
Chris@16
|
142 template<class T>
|
Chris@16
|
143 struct is_lvalue_reference
|
Chris@101
|
144 {
|
Chris@101
|
145 static const bool value = false;
|
Chris@101
|
146 };
|
Chris@16
|
147
|
Chris@16
|
148 template<class T>
|
Chris@16
|
149 struct is_lvalue_reference<T&>
|
Chris@101
|
150 {
|
Chris@101
|
151 static const bool value = true;
|
Chris@101
|
152 };
|
Chris@16
|
153
|
Chris@101
|
154 //////////////////////////////////////
|
Chris@101
|
155 // is_class_or_union
|
Chris@101
|
156 //////////////////////////////////////
|
Chris@16
|
157 template<class T>
|
Chris@16
|
158 struct is_class_or_union
|
Chris@16
|
159 {
|
Chris@101
|
160 struct twochar { char dummy[2]; };
|
Chris@16
|
161 template <class U>
|
Chris@16
|
162 static char is_class_or_union_tester(void(U::*)(void));
|
Chris@16
|
163 template <class U>
|
Chris@16
|
164 static twochar is_class_or_union_tester(...);
|
Chris@16
|
165 static const bool value = sizeof(is_class_or_union_tester<T>(0)) == sizeof(char);
|
Chris@16
|
166 };
|
Chris@16
|
167
|
Chris@101
|
168 //////////////////////////////////////
|
Chris@101
|
169 // addressof
|
Chris@101
|
170 //////////////////////////////////////
|
Chris@101
|
171 template<class T>
|
Chris@101
|
172 struct addr_impl_ref
|
Chris@16
|
173 {
|
Chris@16
|
174 T & v_;
|
Chris@16
|
175 inline addr_impl_ref( T & v ): v_( v ) {}
|
Chris@16
|
176 inline operator T& () const { return v_; }
|
Chris@16
|
177
|
Chris@16
|
178 private:
|
Chris@16
|
179 addr_impl_ref & operator=(const addr_impl_ref &);
|
Chris@16
|
180 };
|
Chris@16
|
181
|
Chris@101
|
182 template<class T>
|
Chris@101
|
183 struct addressof_impl
|
Chris@16
|
184 {
|
Chris@16
|
185 static inline T * f( T & v, long )
|
Chris@16
|
186 {
|
Chris@16
|
187 return reinterpret_cast<T*>(
|
Chris@16
|
188 &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
|
Chris@16
|
189 }
|
Chris@16
|
190
|
Chris@16
|
191 static inline T * f( T * v, int )
|
Chris@16
|
192 { return v; }
|
Chris@16
|
193 };
|
Chris@16
|
194
|
Chris@16
|
195 template<class T>
|
Chris@16
|
196 inline T * addressof( T & v )
|
Chris@16
|
197 {
|
Chris@16
|
198 return ::boost::move_detail::addressof_impl<T>::f
|
Chris@16
|
199 ( ::boost::move_detail::addr_impl_ref<T>( v ), 0 );
|
Chris@16
|
200 }
|
Chris@16
|
201
|
Chris@101
|
202 //////////////////////////////////////
|
Chris@101
|
203 // has_pointer_type
|
Chris@101
|
204 //////////////////////////////////////
|
Chris@101
|
205 template <class T>
|
Chris@101
|
206 struct has_pointer_type
|
Chris@101
|
207 {
|
Chris@101
|
208 struct two { char c[2]; };
|
Chris@101
|
209 template <class U> static two test(...);
|
Chris@101
|
210 template <class U> static char test(typename U::pointer* = 0);
|
Chris@101
|
211 static const bool value = sizeof(test<T>(0)) == 1;
|
Chris@101
|
212 };
|
Chris@101
|
213
|
Chris@101
|
214 //////////////////////////////////////
|
Chris@101
|
215 // is_convertible
|
Chris@101
|
216 //////////////////////////////////////
|
Chris@101
|
217 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
Chris@101
|
218
|
Chris@101
|
219 //use intrinsic since in MSVC
|
Chris@101
|
220 //overaligned types can't go through ellipsis
|
Chris@101
|
221 template <class T, class U>
|
Chris@101
|
222 struct is_convertible
|
Chris@101
|
223 {
|
Chris@101
|
224 static const bool value = __is_convertible_to(T, U);
|
Chris@101
|
225 };
|
Chris@101
|
226
|
Chris@101
|
227 #else
|
Chris@101
|
228
|
Chris@101
|
229 template <class T, class U>
|
Chris@101
|
230 class is_convertible
|
Chris@101
|
231 {
|
Chris@101
|
232 typedef typename add_lvalue_reference<T>::type t_reference;
|
Chris@101
|
233 typedef char true_t;
|
Chris@101
|
234 class false_t { char dummy[2]; };
|
Chris@101
|
235 static false_t dispatch(...);
|
Chris@101
|
236 static true_t dispatch(U);
|
Chris@101
|
237 static t_reference trigger();
|
Chris@101
|
238 public:
|
Chris@101
|
239 static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
|
Chris@101
|
240 };
|
Chris@101
|
241
|
Chris@101
|
242 #endif
|
Chris@101
|
243
|
Chris@101
|
244 //////////////////////////////////////////////////////////////////////////////
|
Chris@101
|
245 //
|
Chris@101
|
246 // has_move_emulation_enabled_impl
|
Chris@101
|
247 //
|
Chris@101
|
248 //////////////////////////////////////////////////////////////////////////////
|
Chris@101
|
249 template<class T>
|
Chris@101
|
250 struct has_move_emulation_enabled_impl
|
Chris@101
|
251 : is_convertible< T, ::boost::rv<T>& >
|
Chris@101
|
252 {};
|
Chris@101
|
253
|
Chris@101
|
254 template<class T>
|
Chris@101
|
255 struct has_move_emulation_enabled_impl<T&>
|
Chris@101
|
256 { static const bool value = false; };
|
Chris@101
|
257
|
Chris@101
|
258 template<class T>
|
Chris@101
|
259 struct has_move_emulation_enabled_impl< ::boost::rv<T> >
|
Chris@101
|
260 { static const bool value = false; };
|
Chris@101
|
261
|
Chris@101
|
262 //////////////////////////////////////////////////////////////////////////////
|
Chris@101
|
263 //
|
Chris@101
|
264 // is_rv_impl
|
Chris@101
|
265 //
|
Chris@101
|
266 //////////////////////////////////////////////////////////////////////////////
|
Chris@101
|
267
|
Chris@101
|
268 template <class T>
|
Chris@101
|
269 struct is_rv_impl
|
Chris@101
|
270 { static const bool value = false; };
|
Chris@101
|
271
|
Chris@101
|
272 template <class T>
|
Chris@101
|
273 struct is_rv_impl< rv<T> >
|
Chris@101
|
274 { static const bool value = true; };
|
Chris@101
|
275
|
Chris@101
|
276 template <class T>
|
Chris@101
|
277 struct is_rv_impl< const rv<T> >
|
Chris@101
|
278 { static const bool value = true; };
|
Chris@101
|
279
|
Chris@101
|
280 // Code from Jeffrey Lee Hellrung, many thanks
|
Chris@101
|
281
|
Chris@101
|
282 template< class T >
|
Chris@101
|
283 struct is_rvalue_reference
|
Chris@101
|
284 { static const bool value = false; };
|
Chris@101
|
285
|
Chris@101
|
286 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
287
|
Chris@101
|
288 template< class T >
|
Chris@101
|
289 struct is_rvalue_reference< T&& >
|
Chris@101
|
290 { static const bool value = true; };
|
Chris@101
|
291
|
Chris@101
|
292 #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
293
|
Chris@101
|
294 template< class T >
|
Chris@101
|
295 struct is_rvalue_reference< boost::rv<T>& >
|
Chris@101
|
296 { static const bool value = true; };
|
Chris@101
|
297
|
Chris@101
|
298 template< class T >
|
Chris@101
|
299 struct is_rvalue_reference< const boost::rv<T>& >
|
Chris@101
|
300 { static const bool value = true; };
|
Chris@101
|
301
|
Chris@101
|
302 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
303
|
Chris@101
|
304 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
305
|
Chris@101
|
306 template< class T >
|
Chris@101
|
307 struct add_rvalue_reference
|
Chris@101
|
308 { typedef T&& type; };
|
Chris@101
|
309
|
Chris@101
|
310 #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
311
|
Chris@101
|
312 namespace detail_add_rvalue_reference
|
Chris@101
|
313 {
|
Chris@101
|
314 template< class T
|
Chris@101
|
315 , bool emulation = has_move_emulation_enabled_impl<T>::value
|
Chris@101
|
316 , bool rv = is_rv_impl<T>::value >
|
Chris@101
|
317 struct add_rvalue_reference_impl { typedef T type; };
|
Chris@101
|
318
|
Chris@101
|
319 template< class T, bool emulation>
|
Chris@101
|
320 struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; };
|
Chris@101
|
321
|
Chris@101
|
322 template< class T, bool rv >
|
Chris@101
|
323 struct add_rvalue_reference_impl< T, true, rv > { typedef ::boost::rv<T>& type; };
|
Chris@101
|
324 } // namespace detail_add_rvalue_reference
|
Chris@101
|
325
|
Chris@101
|
326 template< class T >
|
Chris@101
|
327 struct add_rvalue_reference
|
Chris@101
|
328 : detail_add_rvalue_reference::add_rvalue_reference_impl<T>
|
Chris@101
|
329 { };
|
Chris@101
|
330
|
Chris@101
|
331 template< class T >
|
Chris@101
|
332 struct add_rvalue_reference<T &>
|
Chris@101
|
333 { typedef T & type; };
|
Chris@101
|
334
|
Chris@101
|
335 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
336
|
Chris@101
|
337 template< class T > struct remove_rvalue_reference { typedef T type; };
|
Chris@101
|
338
|
Chris@101
|
339 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
340 template< class T > struct remove_rvalue_reference< T&& > { typedef T type; };
|
Chris@101
|
341 #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
342 template< class T > struct remove_rvalue_reference< rv<T> > { typedef T type; };
|
Chris@101
|
343 template< class T > struct remove_rvalue_reference< const rv<T> > { typedef T type; };
|
Chris@101
|
344 template< class T > struct remove_rvalue_reference< volatile rv<T> > { typedef T type; };
|
Chris@101
|
345 template< class T > struct remove_rvalue_reference< const volatile rv<T> > { typedef T type; };
|
Chris@101
|
346 template< class T > struct remove_rvalue_reference< rv<T>& > { typedef T type; };
|
Chris@101
|
347 template< class T > struct remove_rvalue_reference< const rv<T>& > { typedef T type; };
|
Chris@101
|
348 template< class T > struct remove_rvalue_reference< volatile rv<T>& > { typedef T type; };
|
Chris@101
|
349 template< class T > struct remove_rvalue_reference< const volatile rv<T>& >{ typedef T type; };
|
Chris@101
|
350 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
351
|
Chris@101
|
352 // Ideas from Boost.Move review, Jeffrey Lee Hellrung:
|
Chris@101
|
353 //
|
Chris@101
|
354 //- TypeTraits metafunctions is_lvalue_reference, add_lvalue_reference, and remove_lvalue_reference ?
|
Chris@101
|
355 // Perhaps add_reference and remove_reference can be modified so that they behave wrt emulated rvalue
|
Chris@101
|
356 // references the same as wrt real rvalue references, i.e., add_reference< rv<T>& > -> T& rather than
|
Chris@101
|
357 // rv<T>& (since T&& & -> T&).
|
Chris@101
|
358 //
|
Chris@101
|
359 //- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...?
|
Chris@101
|
360 //
|
Chris@101
|
361 //- An as_lvalue(T& x) function, which amounts to an identity operation in C++0x, but strips emulated
|
Chris@101
|
362 // rvalue references in C++03. This may be necessary to prevent "accidental moves".
|
Chris@101
|
363
|
Chris@16
|
364 } //namespace move_detail {
|
Chris@16
|
365 } //namespace boost {
|
Chris@16
|
366
|
Chris@16
|
367 #endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
|