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
29namespace boost {
30
31namespace movelib {
32
33template <class T>
34struct default_delete;
35
36} //namespace movelib {
37
38#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
39//Forward declare boost::rv
40template <class T> class rv;
41#endif
42
43namespace move_upmu {
44
45//////////////////////////////////////
46// nat
47//////////////////////////////////////
48struct nat{};
49
50//////////////////////////////////////
51// natify
52//////////////////////////////////////
53template <class T> struct natify{};
54
55//////////////////////////////////////
56// if_c
57//////////////////////////////////////
58template<bool C, typename T1, typename T2>
59struct if_c
60{
61 typedef T1 type;
62};
63
64template<typename T1, typename T2>
65struct if_c<false,T1,T2>
66{
67 typedef T2 type;
68};
69
70//////////////////////////////////////
71// if_
72//////////////////////////////////////
73template<typename T1, typename T2, typename T3>
74struct if_ : if_c<0 != T1::value, T2, T3>
75{};
76
77//enable_if_
78template <bool B, class T = nat>
79struct enable_if_c
80{
81 typedef T type;
82};
83
84//////////////////////////////////////
85// enable_if_c
86//////////////////////////////////////
87template <class T>
88struct enable_if_c<false, T> {};
89
90//////////////////////////////////////
91// enable_if
92//////////////////////////////////////
93template <class Cond, class T = nat>
94struct enable_if : public enable_if_c<Cond::value, T> {};
95
96//////////////////////////////////////
97// remove_reference
98//////////////////////////////////////
99template<class T>
100struct remove_reference
101{
102 typedef T type;
103};
104
105template<class T>
106struct remove_reference<T&>
107{
108 typedef T type;
109};
110
111#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
112
113template<class T>
114struct remove_reference<T&&>
115{
116 typedef T type;
117};
118
119#else
120
121template<class T>
122struct remove_reference< rv<T> >
123{
124 typedef T type;
125};
126
127template<class T>
128struct remove_reference< rv<T> &>
129{
130 typedef T type;
131};
132
133template<class T>
134struct remove_reference< const rv<T> &>
135{
136 typedef T type;
137};
138
139
140#endif
141
142//////////////////////////////////////
143// remove_const
144//////////////////////////////////////
145template< class T >
146struct remove_const
147{
148 typedef T type;
149};
150
151template< class T >
152struct remove_const<const T>
153{
154 typedef T type;
155};
156
157//////////////////////////////////////
158// remove_volatile
159//////////////////////////////////////
160template< class T >
161struct remove_volatile
162{
163 typedef T type;
164};
165
166template< class T >
167struct remove_volatile<volatile T>
168{
169 typedef T type;
170};
171
172//////////////////////////////////////
173// remove_cv
174//////////////////////////////////////
175template< class T >
176struct remove_cv
177{
178 typedef typename remove_volatile
179 <typename remove_const<T>::type>::type type;
180};
181
182//////////////////////////////////////
183// remove_extent
184//////////////////////////////////////
185template<class T>
186struct remove_extent
187{
188 typedef T type;
189};
190
191template<class T>
192struct remove_extent<T[]>
193{
194 typedef T type;
195};
196
197template<class T, std::size_t N>
198struct remove_extent<T[N]>
199{
200 typedef T type;
201};
202
203//////////////////////////////////////
204// extent
205//////////////////////////////////////
206
207template<class T, unsigned N = 0>
208struct extent
209{
210 static const std::size_t value = 0;
211};
212
213template<class T>
214struct extent<T[], 0>
215{
216 static const std::size_t value = 0;
217};
218
219template<class T, unsigned N>
220struct extent<T[], N>
221{
222 static const std::size_t value = extent<T, N-1>::value;
223};
224
225template<class T, std::size_t N>
226struct extent<T[N], 0>
227{
228 static const std::size_t value = N;
229};
230
231template<class T, std::size_t I, unsigned N>
232struct 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//////////////////////////////////////
240template<class T>
241struct add_lvalue_reference
242{
243 typedef T& type;
244};
245
246template<class T>
247struct add_lvalue_reference<T&>
248{
249 typedef T& type;
250};
251
252template<>
253struct add_lvalue_reference<void>
254{
255 typedef void type;
256};
257
258template<>
259struct add_lvalue_reference<const void>
260{
261 typedef const void type;
262};
263
264template<>
265struct add_lvalue_reference<volatile void>
266{
267 typedef volatile void type;
268};
269
270template<>
271struct add_lvalue_reference<const volatile void>
272{
273 typedef const volatile void type;
274};
275
276template<class T>
277struct 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//////////////////////////////////////
288template<class T, class U>
289struct is_same
290{
291 static const bool value = false;
292};
293
294template<class T>
295struct is_same<T, T>
296{
297 static const bool value = true;
298};
299
300//////////////////////////////////////
301// is_pointer
302//////////////////////////////////////
303template< class T >
304struct is_pointer
305{
306 static const bool value = false;
307};
308
309template< class T >
310struct is_pointer<T*>
311{
312 static const bool value = true;
313};
314
315//////////////////////////////////////
316// is_reference
317//////////////////////////////////////
318template< class T >
319struct is_reference
320{
321 static const bool value = false;
322};
323
324template< class T >
325struct is_reference<T&>
326{
327 static const bool value = true;
328};
329
330#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
331
332template< class T >
333struct is_reference<T&&>
334{
335 static const bool value = true;
336};
337
338#endif
339
340//////////////////////////////////////
341// is_lvalue_reference
342//////////////////////////////////////
343template<class T>
344struct is_lvalue_reference
345{
346 static const bool value = false;
347};
348
349template<class T>
350struct is_lvalue_reference<T&>
351{
352 static const bool value = true;
353};
354
355//////////////////////////////////////
356// is_array
357//////////////////////////////////////
358template<class T>
359struct is_array
360{
361 static const bool value = false;
362};
363
364template<class T>
365struct is_array<T[]>
366{
367 static const bool value = true;
368};
369
370template<class T, std::size_t N>
371struct is_array<T[N]>
372{
373 static const bool value = true;
374};
375
376//////////////////////////////////////
377// has_pointer_type
378//////////////////////////////////////
379template <class T>
380struct 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//////////////////////////////////////
391template <class T, class D, bool = has_pointer_type<D>::value>
392struct pointer_type_imp
393{
394 typedef typename D::pointer type;
395};
396
397template <class T, class D>
398struct pointer_type_imp<T, D, false>
399{
400 typedef typename remove_extent<T>::type* type;
401};
402
403template <class T, class D>
404struct 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
417template <class T, class U>
418struct is_convertible
419{
420 static const bool value = __is_convertible_to(T, U);
421};
422
423#else
424
425template <class T, class U>
426class 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
453template <typename T>
454struct 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
460template <typename R>
461struct is_unary_function_impl<R (*)()>
462{ static const bool value = true; };
463
464template <typename R>
465struct is_unary_function_impl<R (*)(...)>
466{ static const bool value = true; };
467
468#else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS
469
470template <typename R>
471struct is_unary_function_impl<R (__stdcall*)()>
472{ static const bool value = true; };
473
474#ifndef _MANAGED
475
476template <typename R>
477struct is_unary_function_impl<R (__fastcall*)()>
478{ static const bool value = true; };
479
480#endif
481
482template <typename R>
483struct is_unary_function_impl<R (__cdecl*)()>
484{ static const bool value = true; };
485
486template <typename R>
487struct 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
495template <typename R, class T0>
496struct is_unary_function_impl<R (*)(T0)>
497{ static const bool value = true; };
498
499template <typename R, class T0>
500struct is_unary_function_impl<R (*)(T0...)>
501{ static const bool value = true; };
502
503#else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS
504
505template <typename R, class T0>
506struct is_unary_function_impl<R (__stdcall*)(T0)>
507{ static const bool value = true; };
508
509#ifndef _MANAGED
510
511template <typename R, class T0>
512struct is_unary_function_impl<R (__fastcall*)(T0)>
513{ static const bool value = true; };
514
515#endif
516
517template <typename R, class T0>
518struct is_unary_function_impl<R (__cdecl*)(T0)>
519{ static const bool value = true; };
520
521template <typename R, class T0>
522struct is_unary_function_impl<R (__cdecl*)(T0...)>
523{ static const bool value = true; };
524
525#endif
526
527template <typename T>
528struct is_unary_function_impl<T&>
529{ static const bool value = false; };
530
531template<typename T>
532struct 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
566template< 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 >
572struct missing_virtual_destructor_default_delete
573{ static const bool value = !has_virtual_destructor<T>::value; };
574
575template<class T, class U>
576struct missing_virtual_destructor_default_delete<T, U, false>
577{ static const bool value = false; };
578
579template<class Deleter, class U>
580struct missing_virtual_destructor
581{ static const bool value = false; };
582
583template<class T, class U>
584struct 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