1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2012-2012. |
4 | // Distributed under the Boost Software License, Version 1.0. |
5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | // http://www.boost.org/LICENSE_1_0.txt) |
7 | // |
8 | // See http://www.boost.org/libs/move for documentation. |
9 | // |
10 | ////////////////////////////////////////////////////////////////////////////// |
11 | |
12 | //! \file |
13 | |
14 | #ifndef BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP |
15 | #define BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP |
16 | |
17 | #ifndef BOOST_CONFIG_HPP |
18 | # include <boost/config.hpp> |
19 | #endif |
20 | # |
21 | #if defined(BOOST_HAS_PRAGMA_ONCE) |
22 | # pragma once |
23 | #endif |
24 | |
25 | #include <cstddef> //for std::size_t |
26 | |
27 | //Small meta-typetraits to support move |
28 | |
29 | namespace boost { |
30 | |
31 | namespace movelib { |
32 | |
33 | template <class T> |
34 | struct default_delete; |
35 | |
36 | } //namespace movelib { |
37 | |
38 | #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES |
39 | //Forward declare boost::rv |
40 | template <class T> class rv; |
41 | #endif |
42 | |
43 | namespace move_upmu { |
44 | |
45 | ////////////////////////////////////// |
46 | // nat |
47 | ////////////////////////////////////// |
48 | struct nat{}; |
49 | |
50 | ////////////////////////////////////// |
51 | // natify |
52 | ////////////////////////////////////// |
53 | template <class T> struct natify{}; |
54 | |
55 | ////////////////////////////////////// |
56 | // if_c |
57 | ////////////////////////////////////// |
58 | template<bool C, typename T1, typename T2> |
59 | struct if_c |
60 | { |
61 | typedef T1 type; |
62 | }; |
63 | |
64 | template<typename T1, typename T2> |
65 | struct if_c<false,T1,T2> |
66 | { |
67 | typedef T2 type; |
68 | }; |
69 | |
70 | ////////////////////////////////////// |
71 | // if_ |
72 | ////////////////////////////////////// |
73 | template<typename T1, typename T2, typename T3> |
74 | struct if_ : if_c<0 != T1::value, T2, T3> |
75 | {}; |
76 | |
77 | //enable_if_ |
78 | template <bool B, class T = nat> |
79 | struct enable_if_c |
80 | { |
81 | typedef T type; |
82 | }; |
83 | |
84 | ////////////////////////////////////// |
85 | // enable_if_c |
86 | ////////////////////////////////////// |
87 | template <class T> |
88 | struct enable_if_c<false, T> {}; |
89 | |
90 | ////////////////////////////////////// |
91 | // enable_if |
92 | ////////////////////////////////////// |
93 | template <class Cond, class T = nat> |
94 | struct enable_if : public enable_if_c<Cond::value, T> {}; |
95 | |
96 | ////////////////////////////////////// |
97 | // remove_reference |
98 | ////////////////////////////////////// |
99 | template<class T> |
100 | struct remove_reference |
101 | { |
102 | typedef T type; |
103 | }; |
104 | |
105 | template<class T> |
106 | struct remove_reference<T&> |
107 | { |
108 | typedef T type; |
109 | }; |
110 | |
111 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
112 | |
113 | template<class T> |
114 | struct remove_reference<T&&> |
115 | { |
116 | typedef T type; |
117 | }; |
118 | |
119 | #else |
120 | |
121 | template<class T> |
122 | struct remove_reference< rv<T> > |
123 | { |
124 | typedef T type; |
125 | }; |
126 | |
127 | template<class T> |
128 | struct remove_reference< rv<T> &> |
129 | { |
130 | typedef T type; |
131 | }; |
132 | |
133 | template<class T> |
134 | struct remove_reference< const rv<T> &> |
135 | { |
136 | typedef T type; |
137 | }; |
138 | |
139 | |
140 | #endif |
141 | |
142 | ////////////////////////////////////// |
143 | // remove_const |
144 | ////////////////////////////////////// |
145 | template< class T > |
146 | struct remove_const |
147 | { |
148 | typedef T type; |
149 | }; |
150 | |
151 | template< class T > |
152 | struct remove_const<const T> |
153 | { |
154 | typedef T type; |
155 | }; |
156 | |
157 | ////////////////////////////////////// |
158 | // remove_volatile |
159 | ////////////////////////////////////// |
160 | template< class T > |
161 | struct remove_volatile |
162 | { |
163 | typedef T type; |
164 | }; |
165 | |
166 | template< class T > |
167 | struct remove_volatile<volatile T> |
168 | { |
169 | typedef T type; |
170 | }; |
171 | |
172 | ////////////////////////////////////// |
173 | // remove_cv |
174 | ////////////////////////////////////// |
175 | template< class T > |
176 | struct remove_cv |
177 | { |
178 | typedef typename remove_volatile |
179 | <typename remove_const<T>::type>::type type; |
180 | }; |
181 | |
182 | ////////////////////////////////////// |
183 | // remove_extent |
184 | ////////////////////////////////////// |
185 | template<class T> |
186 | struct remove_extent |
187 | { |
188 | typedef T type; |
189 | }; |
190 | |
191 | template<class T> |
192 | struct remove_extent<T[]> |
193 | { |
194 | typedef T type; |
195 | }; |
196 | |
197 | template<class T, std::size_t N> |
198 | struct remove_extent<T[N]> |
199 | { |
200 | typedef T type; |
201 | }; |
202 | |
203 | ////////////////////////////////////// |
204 | // extent |
205 | ////////////////////////////////////// |
206 | |
207 | template<class T, unsigned N = 0> |
208 | struct extent |
209 | { |
210 | static const std::size_t value = 0; |
211 | }; |
212 | |
213 | template<class T> |
214 | struct extent<T[], 0> |
215 | { |
216 | static const std::size_t value = 0; |
217 | }; |
218 | |
219 | template<class T, unsigned N> |
220 | struct extent<T[], N> |
221 | { |
222 | static const std::size_t value = extent<T, N-1>::value; |
223 | }; |
224 | |
225 | template<class T, std::size_t N> |
226 | struct extent<T[N], 0> |
227 | { |
228 | static const std::size_t value = N; |
229 | }; |
230 | |
231 | template<class T, std::size_t I, unsigned N> |
232 | struct extent<T[I], N> |
233 | { |
234 | static const std::size_t value = extent<T, N-1>::value; |
235 | }; |
236 | |
237 | ////////////////////////////////////// |
238 | // add_lvalue_reference |
239 | ////////////////////////////////////// |
240 | template<class T> |
241 | struct add_lvalue_reference |
242 | { |
243 | typedef T& type; |
244 | }; |
245 | |
246 | template<class T> |
247 | struct add_lvalue_reference<T&> |
248 | { |
249 | typedef T& type; |
250 | }; |
251 | |
252 | template<> |
253 | struct add_lvalue_reference<void> |
254 | { |
255 | typedef void type; |
256 | }; |
257 | |
258 | template<> |
259 | struct add_lvalue_reference<const void> |
260 | { |
261 | typedef const void type; |
262 | }; |
263 | |
264 | template<> |
265 | struct add_lvalue_reference<volatile void> |
266 | { |
267 | typedef volatile void type; |
268 | }; |
269 | |
270 | template<> |
271 | struct add_lvalue_reference<const volatile void> |
272 | { |
273 | typedef const volatile void type; |
274 | }; |
275 | |
276 | template<class T> |
277 | struct add_const_lvalue_reference |
278 | { |
279 | typedef typename remove_reference<T>::type t_unreferenced; |
280 | typedef const t_unreferenced t_unreferenced_const; |
281 | typedef typename add_lvalue_reference |
282 | <t_unreferenced_const>::type type; |
283 | }; |
284 | |
285 | ////////////////////////////////////// |
286 | // is_same |
287 | ////////////////////////////////////// |
288 | template<class T, class U> |
289 | struct is_same |
290 | { |
291 | static const bool value = false; |
292 | }; |
293 | |
294 | template<class T> |
295 | struct is_same<T, T> |
296 | { |
297 | static const bool value = true; |
298 | }; |
299 | |
300 | ////////////////////////////////////// |
301 | // is_pointer |
302 | ////////////////////////////////////// |
303 | template< class T > |
304 | struct is_pointer |
305 | { |
306 | static const bool value = false; |
307 | }; |
308 | |
309 | template< class T > |
310 | struct is_pointer<T*> |
311 | { |
312 | static const bool value = true; |
313 | }; |
314 | |
315 | ////////////////////////////////////// |
316 | // is_reference |
317 | ////////////////////////////////////// |
318 | template< class T > |
319 | struct is_reference |
320 | { |
321 | static const bool value = false; |
322 | }; |
323 | |
324 | template< class T > |
325 | struct is_reference<T&> |
326 | { |
327 | static const bool value = true; |
328 | }; |
329 | |
330 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
331 | |
332 | template< class T > |
333 | struct is_reference<T&&> |
334 | { |
335 | static const bool value = true; |
336 | }; |
337 | |
338 | #endif |
339 | |
340 | ////////////////////////////////////// |
341 | // is_lvalue_reference |
342 | ////////////////////////////////////// |
343 | template<class T> |
344 | struct is_lvalue_reference |
345 | { |
346 | static const bool value = false; |
347 | }; |
348 | |
349 | template<class T> |
350 | struct is_lvalue_reference<T&> |
351 | { |
352 | static const bool value = true; |
353 | }; |
354 | |
355 | ////////////////////////////////////// |
356 | // is_array |
357 | ////////////////////////////////////// |
358 | template<class T> |
359 | struct is_array |
360 | { |
361 | static const bool value = false; |
362 | }; |
363 | |
364 | template<class T> |
365 | struct is_array<T[]> |
366 | { |
367 | static const bool value = true; |
368 | }; |
369 | |
370 | template<class T, std::size_t N> |
371 | struct is_array<T[N]> |
372 | { |
373 | static const bool value = true; |
374 | }; |
375 | |
376 | ////////////////////////////////////// |
377 | // has_pointer_type |
378 | ////////////////////////////////////// |
379 | template <class T> |
380 | struct has_pointer_type |
381 | { |
382 | struct two { char c[2]; }; |
383 | template <class U> static two test(...); |
384 | template <class U> static char test(typename U::pointer* = 0); |
385 | static const bool value = sizeof(test<T>(0)) == 1; |
386 | }; |
387 | |
388 | ////////////////////////////////////// |
389 | // pointer_type |
390 | ////////////////////////////////////// |
391 | template <class T, class D, bool = has_pointer_type<D>::value> |
392 | struct pointer_type_imp |
393 | { |
394 | typedef typename D::pointer type; |
395 | }; |
396 | |
397 | template <class T, class D> |
398 | struct pointer_type_imp<T, D, false> |
399 | { |
400 | typedef typename remove_extent<T>::type* type; |
401 | }; |
402 | |
403 | template <class T, class D> |
404 | struct pointer_type |
405 | { |
406 | typedef typename pointer_type_imp |
407 | <typename remove_extent<T>::type, typename remove_reference<D>::type>::type type; |
408 | }; |
409 | |
410 | ////////////////////////////////////// |
411 | // is_convertible |
412 | ////////////////////////////////////// |
413 | #if defined(_MSC_VER) && (_MSC_VER >= 1400) |
414 | |
415 | //use intrinsic since in MSVC |
416 | //overaligned types can't go through ellipsis |
417 | template <class T, class U> |
418 | struct is_convertible |
419 | { |
420 | static const bool value = __is_convertible_to(T, U); |
421 | }; |
422 | |
423 | #else |
424 | |
425 | template <class T, class U> |
426 | class is_convertible |
427 | { |
428 | typedef typename add_lvalue_reference<T>::type t_reference; |
429 | typedef char true_t; |
430 | class false_t { char dummy[2]; }; |
431 | static false_t dispatch(...); |
432 | static true_t dispatch(U); |
433 | static t_reference trigger(); |
434 | public: |
435 | static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); |
436 | }; |
437 | |
438 | #endif |
439 | |
440 | ////////////////////////////////////// |
441 | // is_unary_function |
442 | ////////////////////////////////////// |
443 | #if defined(BOOST_MSVC) || defined(__BORLANDC_) |
444 | #define BOOST_MOVE_TT_DECL __cdecl |
445 | #else |
446 | #define BOOST_MOVE_TT_DECL |
447 | #endif |
448 | |
449 | #if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(UNDER_CE) |
450 | #define BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS |
451 | #endif |
452 | |
453 | template <typename T> |
454 | struct is_unary_function_impl |
455 | { static const bool value = false; }; |
456 | |
457 | // avoid duplicate definitions of is_unary_function_impl |
458 | #ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS |
459 | |
460 | template <typename R> |
461 | struct is_unary_function_impl<R (*)()> |
462 | { static const bool value = true; }; |
463 | |
464 | template <typename R> |
465 | struct is_unary_function_impl<R (*)(...)> |
466 | { static const bool value = true; }; |
467 | |
468 | #else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS |
469 | |
470 | template <typename R> |
471 | struct is_unary_function_impl<R (__stdcall*)()> |
472 | { static const bool value = true; }; |
473 | |
474 | #ifndef _MANAGED |
475 | |
476 | template <typename R> |
477 | struct is_unary_function_impl<R (__fastcall*)()> |
478 | { static const bool value = true; }; |
479 | |
480 | #endif |
481 | |
482 | template <typename R> |
483 | struct is_unary_function_impl<R (__cdecl*)()> |
484 | { static const bool value = true; }; |
485 | |
486 | template <typename R> |
487 | struct is_unary_function_impl<R (__cdecl*)(...)> |
488 | { static const bool value = true; }; |
489 | |
490 | #endif |
491 | |
492 | // avoid duplicate definitions of is_unary_function_impl |
493 | #ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS |
494 | |
495 | template <typename R, class T0> |
496 | struct is_unary_function_impl<R (*)(T0)> |
497 | { static const bool value = true; }; |
498 | |
499 | template <typename R, class T0> |
500 | struct is_unary_function_impl<R (*)(T0...)> |
501 | { static const bool value = true; }; |
502 | |
503 | #else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS |
504 | |
505 | template <typename R, class T0> |
506 | struct is_unary_function_impl<R (__stdcall*)(T0)> |
507 | { static const bool value = true; }; |
508 | |
509 | #ifndef _MANAGED |
510 | |
511 | template <typename R, class T0> |
512 | struct is_unary_function_impl<R (__fastcall*)(T0)> |
513 | { static const bool value = true; }; |
514 | |
515 | #endif |
516 | |
517 | template <typename R, class T0> |
518 | struct is_unary_function_impl<R (__cdecl*)(T0)> |
519 | { static const bool value = true; }; |
520 | |
521 | template <typename R, class T0> |
522 | struct is_unary_function_impl<R (__cdecl*)(T0...)> |
523 | { static const bool value = true; }; |
524 | |
525 | #endif |
526 | |
527 | template <typename T> |
528 | struct is_unary_function_impl<T&> |
529 | { static const bool value = false; }; |
530 | |
531 | template<typename T> |
532 | struct is_unary_function |
533 | { static const bool value = is_unary_function_impl<T>::value; }; |
534 | |
535 | ////////////////////////////////////// |
536 | // has_virtual_destructor |
537 | ////////////////////////////////////// |
538 | #if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\ |
539 | || (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500)) |
540 | # define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) |
541 | #elif defined(BOOST_CLANG) && defined(__has_feature) |
542 | # if __has_feature(has_virtual_destructor) |
543 | # define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) |
544 | # endif |
545 | #elif defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG) |
546 | # define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) |
547 | #elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600) |
548 | # define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) |
549 | #elif defined(__CODEGEARC__) |
550 | # define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) |
551 | #endif |
552 | |
553 | #ifdef BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR |
554 | template<class T> |
555 | struct has_virtual_destructor{ static const bool value = BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T); }; |
556 | #else |
557 | //If no intrinsic is available you trust the programmer knows what is doing |
558 | template<class T> |
559 | struct has_virtual_destructor{ static const bool value = true; }; |
560 | #endif |
561 | |
562 | ////////////////////////////////////// |
563 | // missing_virtual_destructor |
564 | ////////////////////////////////////// |
565 | |
566 | template< class T, class U |
567 | , bool enable = is_convertible< U*, T*>::value && |
568 | !is_array<T>::value && |
569 | !is_same<typename remove_cv<T>::type, void>::value && |
570 | !is_same<typename remove_cv<U>::type, typename remove_cv<T>::type>::value |
571 | > |
572 | struct missing_virtual_destructor_default_delete |
573 | { static const bool value = !has_virtual_destructor<T>::value; }; |
574 | |
575 | template<class T, class U> |
576 | struct missing_virtual_destructor_default_delete<T, U, false> |
577 | { static const bool value = false; }; |
578 | |
579 | template<class Deleter, class U> |
580 | struct missing_virtual_destructor |
581 | { static const bool value = false; }; |
582 | |
583 | template<class T, class U> |
584 | struct missing_virtual_destructor< ::boost::movelib::default_delete<T>, U > |
585 | : missing_virtual_destructor_default_delete<T, U> |
586 | {}; |
587 | |
588 | } //namespace move_upmu { |
589 | } //namespace boost { |
590 | |
591 | #endif //#ifndef BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP |
592 | |