]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/move/detail/type_traits.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / move / detail / type_traits.hpp
CommitLineData
7c673cae
FG
1//////////////////////////////////////////////////////////////////////////////
2// (C) Copyright John Maddock 2000.
3// (C) Copyright Ion Gaztanaga 2005-2015.
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9// See http://www.boost.org/libs/move for documentation.
10//
11// The alignment and Type traits implementation comes from
12// John Maddock's TypeTraits library.
13//
14// Some other tricks come from Howard Hinnant's papers and StackOverflow replies
15//////////////////////////////////////////////////////////////////////////////
16#ifndef BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP
17#define BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP
18
19#ifndef BOOST_CONFIG_HPP
20# include <boost/config.hpp>
21#endif
22#
23#if defined(BOOST_HAS_PRAGMA_ONCE)
24# pragma once
25#endif
26
27#include <boost/move/detail/config_begin.hpp>
28#include <boost/move/detail/workaround.hpp>
29
30// move/detail
31#include <boost/move/detail/meta_utils.hpp>
32// other
33#include <boost/assert.hpp>
34#include <boost/static_assert.hpp>
35// std
36#include <cstddef>
37
38//Use of Boost.TypeTraits leads to long preprocessed source code due to
39//MPL dependencies. We'll use intrinsics directly and make or own
40//simplified version of TypeTraits.
41//If someday Boost.TypeTraits dependencies are minimized, we should
42//revisit this file redirecting code to Boost.TypeTraits traits.
43
44//These traits don't care about volatile, reference or other checks
45//made by Boost.TypeTraits because no volatile or reference types
46//can be hold in Boost.Containers. This helps to avoid any Boost.TypeTraits
47//dependency.
48
49// Helper macros for builtin compiler support.
50// If your compiler has builtin support for any of the following
51// traits concepts, then redefine the appropriate macros to pick
52// up on the compiler support:
53//
54// (these should largely ignore cv-qualifiers)
55// BOOST_MOVE_IS_POD(T) should evaluate to true if T is a POD type
56// BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) should evaluate to true if "T x;" has no effect
57// BOOST_MOVE_HAS_TRIVIAL_COPY(T) should evaluate to true if T(t) <==> memcpy
58// (Note: this trait does not guarantee T is copy constructible, the copy constructor could be deleted but still be trivial)
59// BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) should evaluate to true if T(boost::move(t)) <==> memcpy
60// BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) should evaluate to true if t = u <==> memcpy
61// (Note: this trait does not guarantee T is assignable , the copy assignmen could be deleted but still be trivial)
62// BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) should evaluate to true if t = boost::move(u) <==> memcpy
63// BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) should evaluate to true if ~T() has no effect
64// BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) should evaluate to true if "T x;" can not throw
65// BOOST_MOVE_HAS_NOTHROW_COPY(T) should evaluate to true if T(t) can not throw
66// BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) should evaluate to true if t = u can not throw
67// BOOST_MOVE_IS_ENUM(T) should evaluate to true it t is a union type.
20effc67
TL
68// BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCT(T) should evaluate to true if T has a non-throwing move constructor.
69// BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) should evaluate to true if T has a non-throwing move assignment operator.
7c673cae
FG
70//
71// The following can also be defined: when detected our implementation is greatly simplified.
72//
73// BOOST_ALIGNMENT_OF(T) should evaluate to the alignment requirements of type T.
74
75#if defined(__MSL_CPP__) && (__MSL_CPP__ >= 0x8000)
76 // Metrowerks compiler is acquiring intrinsic type traits support
77 // post version 8. We hook into the published interface to pick up
78 // user defined specializations as well as compiler intrinsics as
79 // and when they become available:
80# include <msl_utility>
81# define BOOST_MOVE_IS_UNION(T) BOOST_STD_EXTENSION_NAMESPACE::is_union<T>::value
82# define BOOST_MOVE_IS_POD(T) BOOST_STD_EXTENSION_NAMESPACE::is_POD<T>::value
83# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_default_ctor<T>::value
84# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_copy_ctor<T>::value
85# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_assignment<T>::value
86# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_dtor<T>::value
87#endif
88
89#if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\
90 || (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500))
91# define BOOST_MOVE_IS_UNION(T) __is_union(T)
92# define BOOST_MOVE_IS_POD(T) (__is_pod(T) && __has_trivial_constructor(T))
93# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
94# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
95# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T)|| ::boost::move_detail::is_pod<T>::value)
96# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) || ::boost::move_detail::is_pod<T>::value)
97# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) || ::boost::move_detail::is_pod<T>::value)
98# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) || ::boost::move_detail::is_trivially_default_constructible<T>::value)
99# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T) || ::boost::move_detail::is_trivially_copy_constructible<T>::value)
100# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T) || ::boost::move_detail::is_trivially_copy_assignable<T>::value)
101
102# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
103# if defined(_MSC_VER) && (_MSC_VER >= 1700)
104# define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__has_trivial_move_constructor(T) || ::boost::move_detail::is_pod<T>::value)
105# define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) (__has_trivial_move_assign(T) || ::boost::move_detail::is_pod<T>::value)
106# endif
20effc67
TL
107# if _MSC_FULL_VER >= 180020827
108# define BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) (__is_nothrow_assignable(T&, T&&))
109# define BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCT(T) (__is_nothrow_constructible(T, T&&))
110# endif
7c673cae
FG
111#endif
112
20effc67
TL
113#if defined(BOOST_CLANG)
114// BOOST_MOVE_HAS_TRAIT
115# ifdef __has_extension
116# define BOOST_MOVE_HAS_TRAIT(T) __has_extension(T)
117# else
118# define BOOST_MOVE_HAS_TRAIT(T) 0
119# endif
7c673cae 120
20effc67
TL
121// BOOST_MOVE_IS_UNION
122# if BOOST_MOVE_HAS_TRAIT(is_union)
7c673cae
FG
123# define BOOST_MOVE_IS_UNION(T) __is_union(T)
124# endif
20effc67
TL
125
126// BOOST_MOVE_IS_ENUM
127# if BOOST_MOVE_HAS_TRAIT(is_enum)
128# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
129# endif
130
131// BOOST_MOVE_IS_POD
132# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && BOOST_MOVE_HAS_TRAIT(is_pod)
7c673cae
FG
133# define BOOST_MOVE_IS_POD(T) __is_pod(T)
134# endif
20effc67
TL
135
136// BOOST_MOVE_IS_EMPTY
137# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && BOOST_MOVE_HAS_TRAIT(is_empty)
7c673cae
FG
138# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
139# endif
20effc67
TL
140
141// BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR
142# if BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_trivially_constructible)
143# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __is_trivially_constructible(T)
144# elif BOOST_MOVE_HAS_TRAIT(has_trivial_constructor)
7c673cae
FG
145# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
146# endif
20effc67
TL
147
148// BOOST_MOVE_HAS_TRIVIAL_COPY
149# if BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_trivially_constructible)
150# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__is_constructible(T, const T &) && __is_trivially_constructible(T, const T &))
151# elif BOOST_MOVE_HAS_TRAIT(has_trivial_copy)
7c673cae
FG
152# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) __has_trivial_copy(T)
153# endif
20effc67
TL
154
155// BOOST_MOVE_HAS_TRIVIAL_ASSIGN
156# if BOOST_MOVE_HAS_TRAIT(is_assignable) && BOOST_MOVE_HAS_TRAIT(is_trivially_assignable)
157# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__is_assignable(T, const T &) && __is_trivially_assignable(T, const T &))
158# elif BOOST_MOVE_HAS_TRAIT(has_trivial_copy)
159# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) __has_trivial_assign(T)
7c673cae 160# endif
20effc67
TL
161
162// BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR
163# if BOOST_MOVE_HAS_TRAIT(is_trivially_destructible)
164# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __is_trivially_destructible(T)
165# elif BOOST_MOVE_HAS_TRAIT(has_trivial_destructor)
7c673cae
FG
166# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T)
167# endif
20effc67
TL
168
169// BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR
170# if BOOST_MOVE_HAS_TRAIT(is_nothrow_constructible)
171# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __is_nothrow_constructible(T)
172# elif BOOST_MOVE_HAS_TRAIT(has_nothrow_constructor)
7c673cae
FG
173# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __has_nothrow_constructor(T)
174# endif
20effc67
TL
175
176// BOOST_MOVE_HAS_NOTHROW_COPY
177# if BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_nothrow_constructible)
178# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__is_constructible(T, const T &) && __is_nothrow_constructible(T, const T &))
179# elif BOOST_MOVE_HAS_TRAIT(has_nothrow_copy)
7c673cae
FG
180# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T))
181# endif
20effc67
TL
182
183// BOOST_MOVE_HAS_NOTHROW_ASSIGN
184# if BOOST_MOVE_HAS_TRAIT(is_assignable) && BOOST_MOVE_HAS_TRAIT(is_nothrow_assignable)
185# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__is_assignable(T, const T &) && __is_nothrow_assignable(T, const T &))
186# elif BOOST_MOVE_HAS_TRAIT(has_nothrow_assign)
7c673cae
FG
187# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T))
188# endif
20effc67
TL
189
190// BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR
191# if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_trivially_constructible)
192# define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__is_constructible(T, T&&) && __is_trivially_constructible(T, T&&))
193# elif BOOST_MOVE_HAS_TRAIT(has_trivial_move_constructor)
7c673cae
FG
194# define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) __has_trivial_move_constructor(T)
195# endif
20effc67
TL
196
197// BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN
198# if BOOST_MOVE_HAS_TRAIT(is_assignable) && BOOST_MOVE_HAS_TRAIT(is_trivially_assignable)
199# define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) (__is_assignable(T, T&&) && __is_trivially_assignable(T, T&&))
200# elif BOOST_MOVE_HAS_TRAIT(has_trivial_move_assign)
7c673cae
FG
201# define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) __has_trivial_move_assign(T)
202# endif
203# define BOOST_MOVE_ALIGNMENT_OF(T) __alignof(T)
20effc67
TL
204
205#endif //#if defined(BOOST_CLANG)
7c673cae
FG
206
207#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG)
208
209#ifdef BOOST_INTEL
210# define BOOST_MOVE_INTEL_TT_OPTS || ::boost::move_detail::is_pod<T>::value
211#else
212# define BOOST_MOVE_INTEL_TT_OPTS
213#endif
214
215# define BOOST_MOVE_IS_UNION(T) __is_union(T)
216# define BOOST_MOVE_IS_POD(T) __is_pod(T)
217# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
218# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) ((__has_trivial_constructor(T) BOOST_MOVE_INTEL_TT_OPTS))
20effc67
TL
219
220# if defined(BOOST_GCC) && (BOOST_GCC > 50000)
221# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__is_trivially_constructible(T, const T &))
222# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__is_trivially_assignable(T, const T &))
223# else
224# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) ((__has_trivial_copy(T) BOOST_MOVE_INTEL_TT_OPTS))
225# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_MOVE_INTEL_TT_OPTS) )
226# endif
227
7c673cae
FG
228# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) BOOST_MOVE_INTEL_TT_OPTS)
229# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) BOOST_MOVE_INTEL_TT_OPTS)
230# define BOOST_MOVE_HAS_NOTHROW_COPY(T) ((__has_nothrow_copy(T) BOOST_MOVE_INTEL_TT_OPTS))
231# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) ((__has_nothrow_assign(T) BOOST_MOVE_INTEL_TT_OPTS))
232
233# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
234# if (!defined(unix) && !defined(__unix__)) || defined(__LP64__)
235 // GCC sometimes lies about alignment requirements
236 // of type double on 32-bit unix platforms, use the
237 // old implementation instead in that case:
238# define BOOST_MOVE_ALIGNMENT_OF(T) __alignof__(T)
239# endif
240#endif
241
242#if defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600)
243
244# define BOOST_MOVE_IS_UNION(T) __is_union(T)
245# define BOOST_MOVE_IS_POD(T) __is_pod(T)
246# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
247# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
248# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T))
249# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T))
250# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T)
251# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __has_nothrow_constructor(T)
252# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T))
253# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T))
254
255# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
256# define BOOST_MOVE_ALIGNMENT_OF(T) __alignof__(T)
257#endif
258
20effc67 259# if defined(BOOST_CODEGEARC)
7c673cae
FG
260# define BOOST_MOVE_IS_UNION(T) __is_union(T)
261# define BOOST_MOVE_IS_POD(T) __is_pod(T)
262# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
263# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) (__has_trivial_default_constructor(T))
264# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy_constructor(T))
265# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T))
266# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T))
267# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_default_constructor(T))
268# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy_constructor(T))
269# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T))
270
271# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
272# define BOOST_MOVE_ALIGNMENT_OF(T) alignof(T)
273
274#endif
275
276//Fallback definitions
277
278#ifdef BOOST_MOVE_IS_UNION
279 #define BOOST_MOVE_IS_UNION_IMPL(T) BOOST_MOVE_IS_UNION(T)
280#else
281 #define BOOST_MOVE_IS_UNION_IMPL(T) false
282#endif
283
284#ifdef BOOST_MOVE_IS_POD
285 //in some compilers the intrinsic is limited to class types so add scalar and void
286 #define BOOST_MOVE_IS_POD_IMPL(T) (::boost::move_detail::is_scalar<T>::value ||\
287 ::boost::move_detail::is_void<T>::value ||\
288 BOOST_MOVE_IS_POD(T))
289#else
290 #define BOOST_MOVE_IS_POD_IMPL(T) \
291 (::boost::move_detail::is_scalar<T>::value || ::boost::move_detail::is_void<T>::value)
292#endif
293
294#ifdef BOOST_MOVE_IS_EMPTY
295 #define BOOST_MOVE_IS_EMPTY_IMPL(T) BOOST_MOVE_IS_EMPTY(T)
296#else
297 #define BOOST_MOVE_IS_EMPTY_IMPL(T) ::boost::move_detail::is_empty_nonintrinsic<T>::value
298#endif
299
300#ifdef BOOST_MOVE_HAS_TRIVIAL_COPY
301 #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value ||\
302 (::boost::move_detail::is_copy_constructible<T>::value &&\
303 BOOST_MOVE_HAS_TRIVIAL_COPY(T))
304#else
305 #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
306#endif
307
308#ifdef BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR
20effc67 309 #define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value
7c673cae
FG
310#else
311 #define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
312#endif
313
314#ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR
20effc67 315 #define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value
7c673cae
FG
316#else
317 #define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
318#endif
319
320#ifdef BOOST_MOVE_HAS_TRIVIAL_ASSIGN
321 #define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value ||\
322 ( ::boost::move_detail::is_copy_assignable<T>::value &&\
323 BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T))
324#else
325 #define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
326#endif
327
328#ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN
20effc67 329 #define BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) || ::boost::move_detail::is_pod<T>::value
7c673cae
FG
330#else
331 #define BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
332#endif
333
334#ifdef BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR
20effc67 335 #define BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value
7c673cae
FG
336#else
337 #define BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
338#endif
339
340#ifdef BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR
20effc67 341 #define BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value
7c673cae
FG
342#else
343 #define BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
344#endif
345
346#ifdef BOOST_MOVE_HAS_NOTHROW_COPY
20effc67 347 #define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_COPY(T) || ::boost::move_detail::is_pod<T>::value
7c673cae 348#else
20effc67 349 #define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T)
7c673cae
FG
350#endif
351
20effc67
TL
352#ifdef BOOST_MOVE_HAS_NOTHROW_ASSIGN
353 #define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) || ::boost::move_detail::is_pod<T>::value
7c673cae 354#else
20effc67 355 #define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T)
7c673cae
FG
356#endif
357
20effc67
TL
358#ifdef BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCT
359 #define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCT(T) || ::boost::move_detail::is_pod<T>::value
7c673cae 360#else
20effc67 361 #define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T)
7c673cae
FG
362#endif
363
364#ifdef BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN
20effc67 365 #define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) || ::boost::move_detail::is_pod<T>::value
7c673cae 366#else
20effc67 367 #define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T)
7c673cae
FG
368#endif
369
370#ifdef BOOST_MOVE_IS_ENUM
371 #define BOOST_MOVE_IS_ENUM_IMPL(T) BOOST_MOVE_IS_ENUM(T)
372#else
373 #define BOOST_MOVE_IS_ENUM_IMPL(T) ::boost::move_detail::is_enum_nonintrinsic<T>::value
374#endif
375
376namespace boost {
377namespace move_detail {
378
379//////////////////////////
380// is_reference
381//////////////////////////
382template<class T>
383struct is_reference
384{ static const bool value = false; };
385
386template<class T>
387struct is_reference<T&>
388{ static const bool value = true; };
389
390#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
391template<class T>
392struct is_reference<T&&>
393{ static const bool value = true; };
394#endif
395
396//////////////////////////
397// is_pointer
398//////////////////////////
399template<class T>
400struct is_pointer
401{ static const bool value = false; };
402
403template<class T>
404struct is_pointer<T*>
405{ static const bool value = true; };
406
407//////////////////////////
408// is_const
409//////////////////////////
410template<class T>
411struct is_const
412{ static const bool value = false; };
413
414template<class T>
415struct is_const<const T>
416{ static const bool value = true; };
417
418//////////////////////////
419// unvoid_ref
420//////////////////////////
421template <typename T> struct unvoid_ref : add_lvalue_reference<T>{};
422template <> struct unvoid_ref<void> { typedef unvoid_ref & type; };
423template <> struct unvoid_ref<const void> { typedef unvoid_ref & type; };
424template <> struct unvoid_ref<volatile void> { typedef unvoid_ref & type; };
425template <> struct unvoid_ref<const volatile void> { typedef unvoid_ref & type; };
426
427template <typename T>
428struct add_reference : add_lvalue_reference<T>
429{};
430
431//////////////////////////
432// add_const_reference
433//////////////////////////
434template <class T>
435struct add_const_reference
436{ typedef const T &type; };
437
438template <class T>
439struct add_const_reference<T&>
440{ typedef T& type; };
441
442//////////////////////////
443// add_const_if_c
444//////////////////////////
445template<class T, bool Add>
446struct add_const_if_c
447 : if_c<Add, typename add_const<T>::type, T>
448{};
449
450//////////////////////////
451// remove_const
452//////////////////////////
453template<class T>
454struct remove_const
455{ typedef T type; };
456
457template<class T>
458struct remove_const< const T>
459{ typedef T type; };
460
461//////////////////////////
462// remove_cv
463//////////////////////////
464template<typename T> struct remove_cv { typedef T type; };
465template<typename T> struct remove_cv<const T> { typedef T type; };
466template<typename T> struct remove_cv<const volatile T> { typedef T type; };
467template<typename T> struct remove_cv<volatile T> { typedef T type; };
468
20effc67
TL
469//////////////////////////
470// remove_cvref
471//////////////////////////
472template<class T>
473struct remove_cvref
474 : remove_cv<typename remove_reference<T>::type>
475{
476};
477
7c673cae
FG
478//////////////////////////
479// make_unsigned
480//////////////////////////
481template <class T>
482struct make_unsigned_impl { typedef T type; };
483template <> struct make_unsigned_impl<signed char> { typedef unsigned char type; };
484template <> struct make_unsigned_impl<signed short> { typedef unsigned short type; };
485template <> struct make_unsigned_impl<signed int> { typedef unsigned int type; };
486template <> struct make_unsigned_impl<signed long> { typedef unsigned long type; };
487#ifdef BOOST_HAS_LONG_LONG
488template <> struct make_unsigned_impl< ::boost::long_long_type > { typedef ::boost::ulong_long_type type; };
489#endif
490
491template <class T>
492struct make_unsigned
493 : make_unsigned_impl<typename remove_cv<T>::type>
494{};
495
496//////////////////////////
497// is_floating_point
498//////////////////////////
499template<class T> struct is_floating_point_cv { static const bool value = false; };
500template<> struct is_floating_point_cv<float> { static const bool value = true; };
501template<> struct is_floating_point_cv<double> { static const bool value = true; };
502template<> struct is_floating_point_cv<long double> { static const bool value = true; };
503
504template<class T>
505struct is_floating_point
506 : is_floating_point_cv<typename remove_cv<T>::type>
507{};
508
509//////////////////////////
510// is_integral
511//////////////////////////
512template<class T> struct is_integral_cv { static const bool value = false; };
513template<> struct is_integral_cv< bool>{ static const bool value = true; };
514template<> struct is_integral_cv< char>{ static const bool value = true; };
515template<> struct is_integral_cv< unsigned char>{ static const bool value = true; };
516template<> struct is_integral_cv< signed char>{ static const bool value = true; };
517#ifndef BOOST_NO_CXX11_CHAR16_T
518template<> struct is_integral_cv< char16_t>{ static const bool value = true; };
519#endif
520#ifndef BOOST_NO_CXX11_CHAR32_T
521template<> struct is_integral_cv< char32_t>{ static const bool value = true; };
522#endif
523#ifndef BOOST_NO_INTRINSIC_WCHAR_T
524template<> struct is_integral_cv< wchar_t>{ static const bool value = true; };
525#endif
526template<> struct is_integral_cv< short>{ static const bool value = true; };
527template<> struct is_integral_cv< unsigned short>{ static const bool value = true; };
528template<> struct is_integral_cv< int>{ static const bool value = true; };
529template<> struct is_integral_cv< unsigned int>{ static const bool value = true; };
530template<> struct is_integral_cv< long>{ static const bool value = true; };
531template<> struct is_integral_cv< unsigned long>{ static const bool value = true; };
532#ifdef BOOST_HAS_LONG_LONG
533template<> struct is_integral_cv< ::boost:: long_long_type>{ static const bool value = true; };
534template<> struct is_integral_cv< ::boost::ulong_long_type>{ static const bool value = true; };
535#endif
536
537template<class T>
538struct is_integral
539 : public is_integral_cv<typename remove_cv<T>::type>
540{};
541
542//////////////////////////////////////
543// remove_all_extents
544//////////////////////////////////////
545template <class T>
546struct remove_all_extents
547{ typedef T type;};
548
549template <class T>
550struct remove_all_extents<T[]>
551{ typedef typename remove_all_extents<T>::type type; };
552
553template <class T, std::size_t N>
554struct remove_all_extents<T[N]>
555{ typedef typename remove_all_extents<T>::type type;};
556
557//////////////////////////
558// is_scalar
559//////////////////////////
560template<class T>
561struct is_scalar
562{ static const bool value = is_integral<T>::value || is_floating_point<T>::value; };
563
564//////////////////////////
565// is_void
566//////////////////////////
567template<class T>
568struct is_void_cv
569{ static const bool value = false; };
570
571template<>
572struct is_void_cv<void>
573{ static const bool value = true; };
574
575template<class T>
576struct is_void
577 : is_void_cv<typename remove_cv<T>::type>
578{};
579
580//////////////////////////////////////
581// is_array
582//////////////////////////////////////
583template<class T>
584struct is_array
585{ static const bool value = false; };
586
587template<class T>
588struct is_array<T[]>
589{ static const bool value = true; };
590
591template<class T, std::size_t N>
592struct is_array<T[N]>
593{ static const bool value = true; };
594
595//////////////////////////////////////
596// is_member_pointer
597//////////////////////////////////////
598template <class T> struct is_member_pointer_cv { static const bool value = false; };
599template <class T, class U>struct is_member_pointer_cv<T U::*> { static const bool value = true; };
600
601template <class T>
602struct is_member_pointer
603 : is_member_pointer_cv<typename remove_cv<T>::type>
604{};
605
606//////////////////////////////////////
607// is_nullptr_t
608//////////////////////////////////////
609template <class T>
610struct is_nullptr_t_cv
611{ static const bool value = false; };
612
613#if !defined(BOOST_NO_CXX11_NULLPTR)
614template <>
615struct is_nullptr_t_cv
616 #if !defined(BOOST_NO_CXX11_DECLTYPE)
617 <decltype(nullptr)>
618 #else
619 <std::nullptr_t>
620 #endif
621{ static const bool value = true; };
622#endif
623
624template <class T>
625struct is_nullptr_t
626 : is_nullptr_t_cv<typename remove_cv<T>::type>
627{};
628
629//////////////////////////////////////
630// is_function
631//////////////////////////////////////
632//Inspired by libc++, thanks to Howard Hinnant
633//For a function to pointer an lvalue of function type T can be implicitly converted to a prvalue
634//pointer to that function. This does not apply to non-static member functions because lvalues
635//that refer to non-static member functions do not exist.
636template <class T>
637struct is_reference_convertible_to_pointer
638{
639 struct twochar { char dummy[2]; };
640 template <class U> static char test(U*);
641 template <class U> static twochar test(...);
642 static T& source();
643 static const bool value = sizeof(char) == sizeof(test<T>(source()));
644};
645//Filter out:
646// - class types that might have implicit conversions
647// - void (to avoid forming a reference to void later)
648// - references (e.g.: filtering reference to functions)
649// - nullptr_t (convertible to pointer)
650template < class T
651 , bool Filter = is_class_or_union<T>::value ||
652 is_void<T>::value ||
653 is_reference<T>::value ||
654 is_nullptr_t<T>::value >
655struct is_function_impl
656{ static const bool value = is_reference_convertible_to_pointer<T>::value; };
657
658template <class T>
659struct is_function_impl<T, true>
660{ static const bool value = false; };
661
662template <class T>
663struct is_function
664 : is_function_impl<T>
665{};
666
667//////////////////////////////////////
668// is_union
669//////////////////////////////////////
670template<class T>
671struct is_union_noextents_cv
672{ static const bool value = BOOST_MOVE_IS_UNION_IMPL(T); };
673
674template<class T>
675struct is_union
676 : is_union_noextents_cv<typename remove_cv<typename remove_all_extents<T>::type>::type>
677{};
678
679//////////////////////////////////////
680// is_class
681//////////////////////////////////////
682template <class T>
683struct is_class
684{
685 static const bool value = is_class_or_union<T>::value && ! is_union<T>::value;
686};
687
688
689//////////////////////////////////////
690// is_arithmetic
691//////////////////////////////////////
692template <class T>
693struct is_arithmetic
694{
695 static const bool value = is_floating_point<T>::value ||
696 is_integral<T>::value;
697};
698
699//////////////////////////////////////
700// is_member_function_pointer
701//////////////////////////////////////
702template <class T>
703struct is_member_function_pointer_cv
704{
705 static const bool value = false;
706};
707
708template <class T, class C>
709struct is_member_function_pointer_cv<T C::*>
710 : is_function<T>
711{};
712
713template <class T>
714struct is_member_function_pointer
715 : is_member_function_pointer_cv<typename remove_cv<T>::type>
716{};
717
718//////////////////////////////////////
719// is_enum
720//////////////////////////////////////
721#if !defined(BOOST_MOVE_IS_ENUM)
722//Based on (http://howardhinnant.github.io/TypeHiearchy.pdf)
723template <class T>
724struct is_enum_nonintrinsic
725{
726 static const bool value = !is_arithmetic<T>::value &&
727 !is_reference<T>::value &&
728 !is_class_or_union<T>::value &&
729 !is_array<T>::value &&
730 !is_void<T>::value &&
731 !is_nullptr_t<T>::value &&
732 !is_member_pointer<T>::value &&
733 !is_pointer<T>::value &&
734 !is_function<T>::value;
735};
736#endif
737
738template <class T>
739struct is_enum
740{ static const bool value = BOOST_MOVE_IS_ENUM_IMPL(T); };
741
742//////////////////////////////////////
743// is_pod
744//////////////////////////////////////
745template<class T>
746struct is_pod_noextents_cv //for non-c++11 compilers, a safe fallback
747{ static const bool value = BOOST_MOVE_IS_POD_IMPL(T); };
748
749template<class T>
750struct is_pod
751 : is_pod_noextents_cv<typename remove_cv<typename remove_all_extents<T>::type>::type>
752{};
753
754//////////////////////////////////////
755// is_empty
756//////////////////////////////////////
757#if !defined(BOOST_MOVE_IS_EMPTY)
758
759template <typename T>
760struct empty_helper_t1 : public T
761{
762 empty_helper_t1(); // hh compiler bug workaround
763 int i[256];
764 private:
765
766 empty_helper_t1(const empty_helper_t1&);
767 empty_helper_t1& operator=(const empty_helper_t1&);
768};
769
770struct empty_helper_t2 { int i[256]; };
771
772template <typename T, bool IsClass = is_class<T>::value >
773struct is_empty_nonintrinsic
774{
775 static const bool value = false;
776};
777
778template <typename T>
779struct is_empty_nonintrinsic<T, true>
780{
781 static const bool value = sizeof(empty_helper_t1<T>) == sizeof(empty_helper_t2);
782};
783#endif
784
785template <class T>
786struct is_empty
787{ static const bool value = BOOST_MOVE_IS_EMPTY_IMPL(T); };
788
789
790template<class T>
791struct has_boost_move_no_copy_constructor_or_assign_type
792{
793 template <class U>
794 static yes_type test(typename U::boost_move_no_copy_constructor_or_assign*);
795
796 template <class U>
797 static no_type test(...);
798
799 static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
800};
801
802//////////////////////////////////////
803// is_copy_constructible
804//////////////////////////////////////
805#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_NO_CXX11_DECLTYPE) \
806 && !defined(BOOST_INTEL_CXX_VERSION) && \
807 !(defined(BOOST_MSVC) && _MSC_VER == 1800)
808#define BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE
809#endif
810
811template<class T>
812struct is_copy_constructible
813{
814 // Intel compiler has problems with SFINAE for copy constructors and deleted functions:
815 //
816 // error: function *function_name* cannot be referenced -- it is a deleted function
817 // static yes_type test(U&, decltype(U(boost::declval<U&>()))* = 0);
818 // ^
819 // MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See:
820 // https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken
821 #if defined(BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE)
822 template<class U> static typename add_reference<U>::type source();
823 static no_type test(...);
824 #ifdef BOOST_NO_CXX11_DECLTYPE
825 template <class U>
826 static yes_type test(U&, bool_<sizeof(U(source<U>()))>* = 0);
827 #else
828 template <class U>
829 static yes_type test(U&, decltype(U(source<U>()))* = 0);
830 #endif
831 static const bool value = sizeof(test(source<T>())) == sizeof(yes_type);
832 #else
833 static const bool value = !has_boost_move_no_copy_constructor_or_assign_type<T>::value;
834 #endif
835};
836
837
838//////////////////////////////////////
839// is_copy_assignable
840//////////////////////////////////////
841#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_NO_CXX11_DECLTYPE) \
842 && !defined(BOOST_INTEL_CXX_VERSION) && \
843 !(defined(BOOST_MSVC) && _MSC_VER == 1800)
844#define BOOST_MOVE_TT_CXX11_IS_COPY_ASSIGNABLE
845#endif
846
847template <class T>
848struct is_copy_assignable
849{
850// Intel compiler has problems with SFINAE for copy constructors and deleted functions:
851//
852// error: function *function_name* cannot be referenced -- it is a deleted function
853// static boost::type_traits::yes_type test(T1&, decltype(T1(boost::declval<T1&>()))* = 0);
854// ^
855//
856// MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See:
857// https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken
858#if defined(BOOST_MOVE_TT_CXX11_IS_COPY_ASSIGNABLE)
859 typedef char yes_type;
860 struct no_type { char dummy[2]; };
861
862 template <class U> static typename add_reference<U>::type source();
863 template <class U> static decltype(source<U&>() = source<const U&>(), yes_type() ) test(int);
864 template <class> static no_type test(...);
865
866 static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
867#else
868 static const bool value = !has_boost_move_no_copy_constructor_or_assign_type<T>::value;
869#endif
870};
871
872//////////////////////////////////////
873// is_trivially_destructible
874//////////////////////////////////////
875template<class T>
876struct is_trivially_destructible
877{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T); };
878
879//////////////////////////////////////
880// is_trivially_default_constructible
881//////////////////////////////////////
882template<class T>
883struct is_trivially_default_constructible
884{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T); };
885
886//////////////////////////////////////
887// is_trivially_copy_constructible
888//////////////////////////////////////
889template<class T>
890struct is_trivially_copy_constructible
891{
7c673cae
FG
892 static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T);
893};
894
895//////////////////////////////////////
896// is_trivially_move_constructible
897//////////////////////////////////////
898template<class T>
899struct is_trivially_move_constructible
900{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T); };
901
902//////////////////////////////////////
903// is_trivially_copy_assignable
904//////////////////////////////////////
905template<class T>
906struct is_trivially_copy_assignable
907{
7c673cae
FG
908 static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T);
909};
910
911//////////////////////////////////////
912// is_trivially_move_assignable
913//////////////////////////////////////
914template<class T>
915struct is_trivially_move_assignable
916{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T); };
917
918//////////////////////////////////////
919// is_nothrow_default_constructible
920//////////////////////////////////////
921template<class T>
922struct is_nothrow_default_constructible
7c673cae
FG
923{ static const bool value = BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T); };
924
925//////////////////////////////////////
926// is_nothrow_copy_constructible
927//////////////////////////////////////
928template<class T>
929struct is_nothrow_copy_constructible
930{ static const bool value = BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T); };
931
932//////////////////////////////////////
933// is_nothrow_move_constructible
934//////////////////////////////////////
935template<class T>
936struct is_nothrow_move_constructible
937{ static const bool value = BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T); };
938
939//////////////////////////////////////
940// is_nothrow_copy_assignable
941//////////////////////////////////////
942template<class T>
943struct is_nothrow_copy_assignable
944{ static const bool value = BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T); };
945
946//////////////////////////////////////
947// is_nothrow_move_assignable
948//////////////////////////////////////
949template<class T>
950struct is_nothrow_move_assignable
951{ static const bool value = BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T); };
952
953//////////////////////////////////////
954// is_nothrow_swappable
955//////////////////////////////////////
956template<class T>
957struct is_nothrow_swappable
958{
959 static const bool value = is_empty<T>::value || is_pod<T>::value;
960};
961
962//////////////////////////////////////
963// alignment_of
964//////////////////////////////////////
965template <typename T>
966struct alignment_of_hack
967{
968 T t1;
969 char c;
970 T t2;
971 alignment_of_hack();
20effc67 972 ~alignment_of_hack();
7c673cae
FG
973};
974
975template <unsigned A, unsigned S>
976struct alignment_logic
977{ static const std::size_t value = A < S ? A : S; };
978
979template< typename T >
980struct alignment_of_impl
981#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400)
982 // With MSVC both the native __alignof operator
983 // and our own logic gets things wrong from time to time :-(
984 // Using a combination of the two seems to make the most of a bad job:
985 : alignment_logic< sizeof(alignment_of_hack<T>) - 2*sizeof(T), __alignof(T)>
986{};
987#elif !defined(BOOST_MOVE_ALIGNMENT_OF)
988 : alignment_logic< sizeof(alignment_of_hack<T>) - 2*sizeof(T), sizeof(T)>
989{};
990#else
991{ static const std::size_t value = BOOST_MOVE_ALIGNMENT_OF(T); };
992#endif
993
994template< typename T >
995struct alignment_of
996 : alignment_of_impl<T>
997{};
998
999class alignment_dummy;
1000typedef void (*function_ptr)();
1001typedef int (alignment_dummy::*member_ptr);
1002typedef int (alignment_dummy::*member_function_ptr)();
1003struct alignment_struct
1004{ long double dummy[4]; };
1005
1006/////////////////////////////
1007// max_align_t
1008/////////////////////////////
1009//This is not standard, but should work with all compilers
1010union max_align
1011{
1012 char char_;
1013 short short_;
1014 int int_;
1015 long long_;
1016 #ifdef BOOST_HAS_LONG_LONG
1017 ::boost::long_long_type long_long_;
1018 #endif
1019 float float_;
1020 double double_;
1021 void * void_ptr_;
1022 long double long_double_[4];
1023 alignment_dummy *unknown_class_ptr_;
1024 function_ptr function_ptr_;
1025 member_function_ptr member_function_ptr_;
1026 alignment_struct alignment_struct_;
1027};
1028
1029typedef union max_align max_align_t;
1030
1031/////////////////////////////
1032// aligned_storage
1033/////////////////////////////
1034
20effc67
TL
1035#if defined(_MSC_VER) && defined(_M_IX86)
1036
1037// Special version for usual alignments on x86 MSVC because it might crash
1038// when passsing aligned types by value even for 8 byte alignment.
1039template<std::size_t Align>
1040struct aligned_struct;
1041
1042template <> struct aligned_struct<1> { char data; };
1043template <> struct aligned_struct<2> { short data; };
1044template <> struct aligned_struct<4> { int data; };
1045template <> struct aligned_struct<8> { double data; };
1046
1047#define BOOST_MOVE_ALIGNED_STRUCT(x) \
1048 template <> struct aligned_struct<x> { \
1049 __declspec(align(x)) char data; \
1050 }
1051BOOST_MOVE_ALIGNED_STRUCT(16);
1052BOOST_MOVE_ALIGNED_STRUCT(32);
1053BOOST_MOVE_ALIGNED_STRUCT(64);
1054BOOST_MOVE_ALIGNED_STRUCT(128);
1055BOOST_MOVE_ALIGNED_STRUCT(512);
1056BOOST_MOVE_ALIGNED_STRUCT(1024);
1057BOOST_MOVE_ALIGNED_STRUCT(2048);
1058BOOST_MOVE_ALIGNED_STRUCT(4096);
1059
1060template<std::size_t Len, std::size_t Align>
1061union aligned_union
1062{
1063 typedef aligned_struct<Align> aligner_t;
1064 aligner_t aligner;
1065 unsigned char data[Len > sizeof(aligner_t) ? Len : sizeof(aligner_t)];
1066};
1067
1068template<std::size_t Len, std::size_t Align>
1069struct aligned_storage_impl
1070{
1071 typedef aligned_union<Len, Align> type;
1072};
1073
1074#elif !defined(BOOST_NO_ALIGNMENT)
7c673cae
FG
1075
1076template<std::size_t Len, std::size_t Align>
b32b8144 1077struct aligned_struct;
7c673cae
FG
1078
1079#define BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(A)\
1080template<std::size_t Len>\
b32b8144 1081struct BOOST_ALIGNMENT(A) aligned_struct<Len, A>\
7c673cae 1082{\
92f5a8d4 1083 unsigned char data[Len];\
7c673cae
FG
1084};\
1085//
1086
1087//Up to 4K alignment (typical page size)
1088BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x1)
1089BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x2)
1090BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x4)
1091BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x8)
1092BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x10)
1093BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x20)
1094BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x40)
1095BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x80)
1096BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x100)
1097BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x200)
1098BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x400)
1099BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x800)
1100BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x1000)
1101
1102#undef BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT
1103
b32b8144
FG
1104// Workaround for bogus [-Wignored-attributes] warning on GCC 6.x/7.x: don't use a type that "directly" carries the alignment attribute.
1105// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82270
1106template<std::size_t Len, std::size_t Align>
11fdf7f2 1107union aligned_struct_wrapper
b32b8144 1108{
20effc67 1109 typedef aligned_struct<Len, Align> aligner_t;
11fdf7f2 1110 aligned_struct<Len, Align> aligner;
20effc67 1111 unsigned char data[Len > sizeof(aligner_t) ? Len : sizeof(aligner_t)];
b32b8144
FG
1112};
1113
1114template<std::size_t Len, std::size_t Align>
1115struct aligned_storage_impl
1116{
1117 typedef aligned_struct_wrapper<Len, Align> type;
1118};
1119
7c673cae
FG
1120#else //BOOST_NO_ALIGNMENT
1121
1122template<class T, std::size_t Len>
1123union aligned_union
1124{
1125 T aligner;
20effc67 1126 unsigned char data[Len > sizeof(T) ? Len : sizeof(T)];
7c673cae
FG
1127};
1128
1129template<std::size_t Len, std::size_t Align, class T, bool Ok>
1130struct aligned_next;
1131
1132template<std::size_t Len, std::size_t Align, class T>
1133struct aligned_next<Len, Align, T, true>
1134{
1135 BOOST_STATIC_ASSERT((alignment_of<T>::value == Align));
1136 typedef aligned_union<T, Len> type;
1137};
1138
1139//End of search defaults to max_align_t
1140template<std::size_t Len, std::size_t Align>
1141struct aligned_next<Len, Align, max_align_t, false>
1142{ typedef aligned_union<max_align_t, Len> type; };
1143
1144//Now define a search list through types
1145#define BOOST_MOVE_ALIGNED_NEXT_STEP(TYPE, NEXT_TYPE)\
1146 template<std::size_t Len, std::size_t Align>\
1147 struct aligned_next<Len, Align, TYPE, false>\
1148 : aligned_next<Len, Align, NEXT_TYPE, Align == alignment_of<NEXT_TYPE>::value>\
1149 {};\
1150 //
1151 BOOST_MOVE_ALIGNED_NEXT_STEP(long double, max_align_t)
1152 BOOST_MOVE_ALIGNED_NEXT_STEP(double, long double)
1153 #ifdef BOOST_HAS_LONG_LONG
1154 BOOST_MOVE_ALIGNED_NEXT_STEP(::boost::long_long_type, double)
1155 BOOST_MOVE_ALIGNED_NEXT_STEP(long, ::boost::long_long_type)
1156 #else
1157 BOOST_MOVE_ALIGNED_NEXT_STEP(long, double)
1158 #endif
1159 BOOST_MOVE_ALIGNED_NEXT_STEP(int, long)
1160 BOOST_MOVE_ALIGNED_NEXT_STEP(short, int)
1161 BOOST_MOVE_ALIGNED_NEXT_STEP(char, short)
1162#undef BOOST_MOVE_ALIGNED_NEXT_STEP
1163
1164template<std::size_t Len, std::size_t Align>
1165struct aligned_storage_impl
1166 : aligned_next<Len, Align, char, Align == alignment_of<char>::value>
1167{};
1168
1169#endif
1170
1171template<std::size_t Len, std::size_t Align = alignment_of<max_align_t>::value>
1172struct aligned_storage
1173{
1174 //Sanity checks for input parameters
1175 BOOST_STATIC_ASSERT(Align > 0);
1176
1177 //Sanity checks for output type
1178 typedef typename aligned_storage_impl<Len ? Len : 1, Align>::type type;
1179 static const std::size_t value = alignment_of<type>::value;
1180 BOOST_STATIC_ASSERT(value >= Align);
1181 BOOST_STATIC_ASSERT((value % Align) == 0);
1182
1183 //Just in case someone instantiates aligned_storage
1184 //instead of aligned_storage::type (typical error).
1185 private:
1186 aligned_storage();
1187};
1188
1189} //namespace move_detail {
1190} //namespace boost {
1191
1192#include <boost/move/detail/config_end.hpp>
1193
1194#endif //#ifndef BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP