1*e4b17023SJohn Marino// C++11 type_traits -*- C++ -*-
2*e4b17023SJohn Marino
3*e4b17023SJohn Marino// Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4*e4b17023SJohn Marino//
5*e4b17023SJohn Marino// This file is part of the GNU ISO C++ Library.  This library is free
6*e4b17023SJohn Marino// software; you can redistribute it and/or modify it under the
7*e4b17023SJohn Marino// terms of the GNU General Public License as published by the
8*e4b17023SJohn Marino// Free Software Foundation; either version 3, or (at your option)
9*e4b17023SJohn Marino// any later version.
10*e4b17023SJohn Marino
11*e4b17023SJohn Marino// This library is distributed in the hope that it will be useful,
12*e4b17023SJohn Marino// but WITHOUT ANY WARRANTY; without even the implied warranty of
13*e4b17023SJohn Marino// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*e4b17023SJohn Marino// GNU General Public License for more details.
15*e4b17023SJohn Marino
16*e4b17023SJohn Marino// Under Section 7 of GPL version 3, you are granted additional
17*e4b17023SJohn Marino// permissions described in the GCC Runtime Library Exception, version
18*e4b17023SJohn Marino// 3.1, as published by the Free Software Foundation.
19*e4b17023SJohn Marino
20*e4b17023SJohn Marino// You should have received a copy of the GNU General Public License and
21*e4b17023SJohn Marino// a copy of the GCC Runtime Library Exception along with this program;
22*e4b17023SJohn Marino// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*e4b17023SJohn Marino// <http://www.gnu.org/licenses/>.
24*e4b17023SJohn Marino
25*e4b17023SJohn Marino/** @file include/type_traits
26*e4b17023SJohn Marino *  This is a Standard C++ Library header.
27*e4b17023SJohn Marino */
28*e4b17023SJohn Marino
29*e4b17023SJohn Marino#ifndef _GLIBCXX_TYPE_TRAITS
30*e4b17023SJohn Marino#define _GLIBCXX_TYPE_TRAITS 1
31*e4b17023SJohn Marino
32*e4b17023SJohn Marino#pragma GCC system_header
33*e4b17023SJohn Marino
34*e4b17023SJohn Marino#ifndef __GXX_EXPERIMENTAL_CXX0X__
35*e4b17023SJohn Marino# include <bits/c++0x_warning.h>
36*e4b17023SJohn Marino#else
37*e4b17023SJohn Marino
38*e4b17023SJohn Marino#include <bits/c++config.h>
39*e4b17023SJohn Marino
40*e4b17023SJohn Marinonamespace std _GLIBCXX_VISIBILITY(default)
41*e4b17023SJohn Marino{
42*e4b17023SJohn Marino_GLIBCXX_BEGIN_NAMESPACE_VERSION
43*e4b17023SJohn Marino
44*e4b17023SJohn Marino  /**
45*e4b17023SJohn Marino   * @defgroup metaprogramming Metaprogramming and type traits
46*e4b17023SJohn Marino   * @ingroup utilities
47*e4b17023SJohn Marino   *
48*e4b17023SJohn Marino   * Template utilities for compile-time introspection and modification,
49*e4b17023SJohn Marino   * including type classification traits, type property inspection traits
50*e4b17023SJohn Marino   * and type transformation traits.
51*e4b17023SJohn Marino   *
52*e4b17023SJohn Marino   * @{
53*e4b17023SJohn Marino   */
54*e4b17023SJohn Marino
55*e4b17023SJohn Marino  /// integral_constant
56*e4b17023SJohn Marino  template<typename _Tp, _Tp __v>
57*e4b17023SJohn Marino    struct integral_constant
58*e4b17023SJohn Marino    {
59*e4b17023SJohn Marino      static constexpr _Tp                  value = __v;
60*e4b17023SJohn Marino      typedef _Tp                           value_type;
61*e4b17023SJohn Marino      typedef integral_constant<_Tp, __v>   type;
62*e4b17023SJohn Marino      constexpr operator value_type() { return value; }
63*e4b17023SJohn Marino    };
64*e4b17023SJohn Marino
65*e4b17023SJohn Marino  /// The type used as a compile-time boolean with true value.
66*e4b17023SJohn Marino  typedef integral_constant<bool, true>     true_type;
67*e4b17023SJohn Marino
68*e4b17023SJohn Marino  /// The type used as a compile-time boolean with false value.
69*e4b17023SJohn Marino  typedef integral_constant<bool, false>    false_type;
70*e4b17023SJohn Marino
71*e4b17023SJohn Marino  template<typename _Tp, _Tp __v>
72*e4b17023SJohn Marino    constexpr _Tp integral_constant<_Tp, __v>::value;
73*e4b17023SJohn Marino
74*e4b17023SJohn Marino  // Meta programming helper types.
75*e4b17023SJohn Marino
76*e4b17023SJohn Marino  template<bool, typename, typename>
77*e4b17023SJohn Marino    struct conditional;
78*e4b17023SJohn Marino
79*e4b17023SJohn Marino  template<typename...>
80*e4b17023SJohn Marino    struct __or_;
81*e4b17023SJohn Marino
82*e4b17023SJohn Marino  template<>
83*e4b17023SJohn Marino    struct __or_<>
84*e4b17023SJohn Marino    : public false_type
85*e4b17023SJohn Marino    { };
86*e4b17023SJohn Marino
87*e4b17023SJohn Marino  template<typename _B1>
88*e4b17023SJohn Marino    struct __or_<_B1>
89*e4b17023SJohn Marino    : public _B1
90*e4b17023SJohn Marino    { };
91*e4b17023SJohn Marino
92*e4b17023SJohn Marino  template<typename _B1, typename _B2>
93*e4b17023SJohn Marino    struct __or_<_B1, _B2>
94*e4b17023SJohn Marino    : public conditional<_B1::value, _B1, _B2>::type
95*e4b17023SJohn Marino    { };
96*e4b17023SJohn Marino
97*e4b17023SJohn Marino  template<typename _B1, typename _B2, typename _B3, typename... _Bn>
98*e4b17023SJohn Marino    struct __or_<_B1, _B2, _B3, _Bn...>
99*e4b17023SJohn Marino    : public conditional<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>::type
100*e4b17023SJohn Marino    { };
101*e4b17023SJohn Marino
102*e4b17023SJohn Marino  template<typename...>
103*e4b17023SJohn Marino    struct __and_;
104*e4b17023SJohn Marino
105*e4b17023SJohn Marino  template<>
106*e4b17023SJohn Marino    struct __and_<>
107*e4b17023SJohn Marino    : public true_type
108*e4b17023SJohn Marino    { };
109*e4b17023SJohn Marino
110*e4b17023SJohn Marino  template<typename _B1>
111*e4b17023SJohn Marino    struct __and_<_B1>
112*e4b17023SJohn Marino    : public _B1
113*e4b17023SJohn Marino    { };
114*e4b17023SJohn Marino
115*e4b17023SJohn Marino  template<typename _B1, typename _B2>
116*e4b17023SJohn Marino    struct __and_<_B1, _B2>
117*e4b17023SJohn Marino    : public conditional<_B1::value, _B2, _B1>::type
118*e4b17023SJohn Marino    { };
119*e4b17023SJohn Marino
120*e4b17023SJohn Marino  template<typename _B1, typename _B2, typename _B3, typename... _Bn>
121*e4b17023SJohn Marino    struct __and_<_B1, _B2, _B3, _Bn...>
122*e4b17023SJohn Marino    : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type
123*e4b17023SJohn Marino    { };
124*e4b17023SJohn Marino
125*e4b17023SJohn Marino  template<typename _Pp>
126*e4b17023SJohn Marino    struct __not_
127*e4b17023SJohn Marino    : public integral_constant<bool, !_Pp::value>
128*e4b17023SJohn Marino    { };
129*e4b17023SJohn Marino
130*e4b17023SJohn Marino  struct __sfinae_types
131*e4b17023SJohn Marino  {
132*e4b17023SJohn Marino    typedef char __one;
133*e4b17023SJohn Marino    typedef struct { char __arr[2]; } __two;
134*e4b17023SJohn Marino  };
135*e4b17023SJohn Marino
136*e4b17023SJohn Marino  // primary type categories.
137*e4b17023SJohn Marino
138*e4b17023SJohn Marino  template<typename>
139*e4b17023SJohn Marino    struct remove_cv;
140*e4b17023SJohn Marino
141*e4b17023SJohn Marino  template<typename>
142*e4b17023SJohn Marino    struct __is_void_helper
143*e4b17023SJohn Marino    : public false_type { };
144*e4b17023SJohn Marino
145*e4b17023SJohn Marino  template<>
146*e4b17023SJohn Marino    struct __is_void_helper<void>
147*e4b17023SJohn Marino    : public true_type { };
148*e4b17023SJohn Marino
149*e4b17023SJohn Marino  /// is_void
150*e4b17023SJohn Marino  template<typename _Tp>
151*e4b17023SJohn Marino    struct is_void
152*e4b17023SJohn Marino    : public integral_constant<bool, (__is_void_helper<typename
153*e4b17023SJohn Marino				      remove_cv<_Tp>::type>::value)>
154*e4b17023SJohn Marino    { };
155*e4b17023SJohn Marino
156*e4b17023SJohn Marino  template<typename>
157*e4b17023SJohn Marino    struct __is_integral_helper
158*e4b17023SJohn Marino    : public false_type { };
159*e4b17023SJohn Marino
160*e4b17023SJohn Marino  template<>
161*e4b17023SJohn Marino    struct __is_integral_helper<bool>
162*e4b17023SJohn Marino    : public true_type { };
163*e4b17023SJohn Marino
164*e4b17023SJohn Marino  template<>
165*e4b17023SJohn Marino    struct __is_integral_helper<char>
166*e4b17023SJohn Marino    : public true_type { };
167*e4b17023SJohn Marino
168*e4b17023SJohn Marino  template<>
169*e4b17023SJohn Marino    struct __is_integral_helper<signed char>
170*e4b17023SJohn Marino    : public true_type { };
171*e4b17023SJohn Marino
172*e4b17023SJohn Marino  template<>
173*e4b17023SJohn Marino    struct __is_integral_helper<unsigned char>
174*e4b17023SJohn Marino    : public true_type { };
175*e4b17023SJohn Marino
176*e4b17023SJohn Marino#ifdef _GLIBCXX_USE_WCHAR_T
177*e4b17023SJohn Marino  template<>
178*e4b17023SJohn Marino    struct __is_integral_helper<wchar_t>
179*e4b17023SJohn Marino    : public true_type { };
180*e4b17023SJohn Marino#endif
181*e4b17023SJohn Marino
182*e4b17023SJohn Marino  template<>
183*e4b17023SJohn Marino    struct __is_integral_helper<char16_t>
184*e4b17023SJohn Marino    : public true_type { };
185*e4b17023SJohn Marino
186*e4b17023SJohn Marino  template<>
187*e4b17023SJohn Marino    struct __is_integral_helper<char32_t>
188*e4b17023SJohn Marino    : public true_type { };
189*e4b17023SJohn Marino
190*e4b17023SJohn Marino  template<>
191*e4b17023SJohn Marino    struct __is_integral_helper<short>
192*e4b17023SJohn Marino    : public true_type { };
193*e4b17023SJohn Marino
194*e4b17023SJohn Marino  template<>
195*e4b17023SJohn Marino    struct __is_integral_helper<unsigned short>
196*e4b17023SJohn Marino    : public true_type { };
197*e4b17023SJohn Marino
198*e4b17023SJohn Marino  template<>
199*e4b17023SJohn Marino    struct __is_integral_helper<int>
200*e4b17023SJohn Marino    : public true_type { };
201*e4b17023SJohn Marino
202*e4b17023SJohn Marino  template<>
203*e4b17023SJohn Marino    struct __is_integral_helper<unsigned int>
204*e4b17023SJohn Marino    : public true_type { };
205*e4b17023SJohn Marino
206*e4b17023SJohn Marino  template<>
207*e4b17023SJohn Marino    struct __is_integral_helper<long>
208*e4b17023SJohn Marino    : public true_type { };
209*e4b17023SJohn Marino
210*e4b17023SJohn Marino  template<>
211*e4b17023SJohn Marino    struct __is_integral_helper<unsigned long>
212*e4b17023SJohn Marino    : public true_type { };
213*e4b17023SJohn Marino
214*e4b17023SJohn Marino  template<>
215*e4b17023SJohn Marino    struct __is_integral_helper<long long>
216*e4b17023SJohn Marino    : public true_type { };
217*e4b17023SJohn Marino
218*e4b17023SJohn Marino  template<>
219*e4b17023SJohn Marino    struct __is_integral_helper<unsigned long long>
220*e4b17023SJohn Marino    : public true_type { };
221*e4b17023SJohn Marino
222*e4b17023SJohn Marino#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
223*e4b17023SJohn Marino  template<>
224*e4b17023SJohn Marino    struct __is_integral_helper<__int128>
225*e4b17023SJohn Marino    : public true_type { };
226*e4b17023SJohn Marino
227*e4b17023SJohn Marino  template<>
228*e4b17023SJohn Marino    struct __is_integral_helper<unsigned __int128>
229*e4b17023SJohn Marino    : public true_type { };
230*e4b17023SJohn Marino#endif
231*e4b17023SJohn Marino
232*e4b17023SJohn Marino  /// is_integral
233*e4b17023SJohn Marino  template<typename _Tp>
234*e4b17023SJohn Marino    struct is_integral
235*e4b17023SJohn Marino    : public integral_constant<bool, (__is_integral_helper<typename
236*e4b17023SJohn Marino				      remove_cv<_Tp>::type>::value)>
237*e4b17023SJohn Marino    { };
238*e4b17023SJohn Marino
239*e4b17023SJohn Marino  template<typename>
240*e4b17023SJohn Marino    struct __is_floating_point_helper
241*e4b17023SJohn Marino    : public false_type { };
242*e4b17023SJohn Marino
243*e4b17023SJohn Marino  template<>
244*e4b17023SJohn Marino    struct __is_floating_point_helper<float>
245*e4b17023SJohn Marino    : public true_type { };
246*e4b17023SJohn Marino
247*e4b17023SJohn Marino  template<>
248*e4b17023SJohn Marino    struct __is_floating_point_helper<double>
249*e4b17023SJohn Marino    : public true_type { };
250*e4b17023SJohn Marino
251*e4b17023SJohn Marino  template<>
252*e4b17023SJohn Marino    struct __is_floating_point_helper<long double>
253*e4b17023SJohn Marino    : public true_type { };
254*e4b17023SJohn Marino
255*e4b17023SJohn Marino#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
256*e4b17023SJohn Marino  template<>
257*e4b17023SJohn Marino    struct __is_floating_point_helper<__float128>
258*e4b17023SJohn Marino    : public true_type { };
259*e4b17023SJohn Marino#endif
260*e4b17023SJohn Marino
261*e4b17023SJohn Marino  /// is_floating_point
262*e4b17023SJohn Marino  template<typename _Tp>
263*e4b17023SJohn Marino    struct is_floating_point
264*e4b17023SJohn Marino    : public integral_constant<bool, (__is_floating_point_helper<typename
265*e4b17023SJohn Marino				      remove_cv<_Tp>::type>::value)>
266*e4b17023SJohn Marino    { };
267*e4b17023SJohn Marino
268*e4b17023SJohn Marino  /// is_array
269*e4b17023SJohn Marino  template<typename>
270*e4b17023SJohn Marino    struct is_array
271*e4b17023SJohn Marino    : public false_type { };
272*e4b17023SJohn Marino
273*e4b17023SJohn Marino  template<typename _Tp, std::size_t _Size>
274*e4b17023SJohn Marino    struct is_array<_Tp[_Size]>
275*e4b17023SJohn Marino    : public true_type { };
276*e4b17023SJohn Marino
277*e4b17023SJohn Marino  template<typename _Tp>
278*e4b17023SJohn Marino    struct is_array<_Tp[]>
279*e4b17023SJohn Marino    : public true_type { };
280*e4b17023SJohn Marino
281*e4b17023SJohn Marino  template<typename>
282*e4b17023SJohn Marino    struct __is_pointer_helper
283*e4b17023SJohn Marino    : public false_type { };
284*e4b17023SJohn Marino
285*e4b17023SJohn Marino  template<typename _Tp>
286*e4b17023SJohn Marino    struct __is_pointer_helper<_Tp*>
287*e4b17023SJohn Marino    : public true_type { };
288*e4b17023SJohn Marino
289*e4b17023SJohn Marino  /// is_pointer
290*e4b17023SJohn Marino  template<typename _Tp>
291*e4b17023SJohn Marino    struct is_pointer
292*e4b17023SJohn Marino    : public integral_constant<bool, (__is_pointer_helper<typename
293*e4b17023SJohn Marino				      remove_cv<_Tp>::type>::value)>
294*e4b17023SJohn Marino    { };
295*e4b17023SJohn Marino
296*e4b17023SJohn Marino  /// is_lvalue_reference
297*e4b17023SJohn Marino  template<typename>
298*e4b17023SJohn Marino    struct is_lvalue_reference
299*e4b17023SJohn Marino    : public false_type { };
300*e4b17023SJohn Marino
301*e4b17023SJohn Marino  template<typename _Tp>
302*e4b17023SJohn Marino    struct is_lvalue_reference<_Tp&>
303*e4b17023SJohn Marino    : public true_type { };
304*e4b17023SJohn Marino
305*e4b17023SJohn Marino  /// is_rvalue_reference
306*e4b17023SJohn Marino  template<typename>
307*e4b17023SJohn Marino    struct is_rvalue_reference
308*e4b17023SJohn Marino    : public false_type { };
309*e4b17023SJohn Marino
310*e4b17023SJohn Marino  template<typename _Tp>
311*e4b17023SJohn Marino    struct is_rvalue_reference<_Tp&&>
312*e4b17023SJohn Marino    : public true_type { };
313*e4b17023SJohn Marino
314*e4b17023SJohn Marino  template<typename>
315*e4b17023SJohn Marino    struct is_function;
316*e4b17023SJohn Marino
317*e4b17023SJohn Marino  template<typename>
318*e4b17023SJohn Marino    struct __is_member_object_pointer_helper
319*e4b17023SJohn Marino    : public false_type { };
320*e4b17023SJohn Marino
321*e4b17023SJohn Marino  template<typename _Tp, typename _Cp>
322*e4b17023SJohn Marino    struct __is_member_object_pointer_helper<_Tp _Cp::*>
323*e4b17023SJohn Marino    : public integral_constant<bool, !is_function<_Tp>::value> { };
324*e4b17023SJohn Marino
325*e4b17023SJohn Marino  /// is_member_object_pointer
326*e4b17023SJohn Marino  template<typename _Tp>
327*e4b17023SJohn Marino    struct is_member_object_pointer
328*e4b17023SJohn Marino    : public integral_constant<bool, (__is_member_object_pointer_helper<
329*e4b17023SJohn Marino				      typename remove_cv<_Tp>::type>::value)>
330*e4b17023SJohn Marino    { };
331*e4b17023SJohn Marino
332*e4b17023SJohn Marino  template<typename>
333*e4b17023SJohn Marino    struct __is_member_function_pointer_helper
334*e4b17023SJohn Marino    : public false_type { };
335*e4b17023SJohn Marino
336*e4b17023SJohn Marino  template<typename _Tp, typename _Cp>
337*e4b17023SJohn Marino    struct __is_member_function_pointer_helper<_Tp _Cp::*>
338*e4b17023SJohn Marino    : public integral_constant<bool, is_function<_Tp>::value> { };
339*e4b17023SJohn Marino
340*e4b17023SJohn Marino  /// is_member_function_pointer
341*e4b17023SJohn Marino  template<typename _Tp>
342*e4b17023SJohn Marino    struct is_member_function_pointer
343*e4b17023SJohn Marino    : public integral_constant<bool, (__is_member_function_pointer_helper<
344*e4b17023SJohn Marino				      typename remove_cv<_Tp>::type>::value)>
345*e4b17023SJohn Marino    { };
346*e4b17023SJohn Marino
347*e4b17023SJohn Marino  /// is_enum
348*e4b17023SJohn Marino  template<typename _Tp>
349*e4b17023SJohn Marino    struct is_enum
350*e4b17023SJohn Marino    : public integral_constant<bool, __is_enum(_Tp)>
351*e4b17023SJohn Marino    { };
352*e4b17023SJohn Marino
353*e4b17023SJohn Marino  /// is_union
354*e4b17023SJohn Marino  template<typename _Tp>
355*e4b17023SJohn Marino    struct is_union
356*e4b17023SJohn Marino    : public integral_constant<bool, __is_union(_Tp)>
357*e4b17023SJohn Marino    { };
358*e4b17023SJohn Marino
359*e4b17023SJohn Marino  /// is_class
360*e4b17023SJohn Marino  template<typename _Tp>
361*e4b17023SJohn Marino    struct is_class
362*e4b17023SJohn Marino    : public integral_constant<bool, __is_class(_Tp)>
363*e4b17023SJohn Marino    { };
364*e4b17023SJohn Marino
365*e4b17023SJohn Marino  /// is_function
366*e4b17023SJohn Marino  template<typename>
367*e4b17023SJohn Marino    struct is_function
368*e4b17023SJohn Marino    : public false_type { };
369*e4b17023SJohn Marino
370*e4b17023SJohn Marino  template<typename _Res, typename... _ArgTypes>
371*e4b17023SJohn Marino    struct is_function<_Res(_ArgTypes...)>
372*e4b17023SJohn Marino    : public true_type { };
373*e4b17023SJohn Marino
374*e4b17023SJohn Marino  template<typename _Res, typename... _ArgTypes>
375*e4b17023SJohn Marino    struct is_function<_Res(_ArgTypes......)>
376*e4b17023SJohn Marino    : public true_type { };
377*e4b17023SJohn Marino
378*e4b17023SJohn Marino  template<typename _Res, typename... _ArgTypes>
379*e4b17023SJohn Marino    struct is_function<_Res(_ArgTypes...) const>
380*e4b17023SJohn Marino    : public true_type { };
381*e4b17023SJohn Marino
382*e4b17023SJohn Marino  template<typename _Res, typename... _ArgTypes>
383*e4b17023SJohn Marino    struct is_function<_Res(_ArgTypes......) const>
384*e4b17023SJohn Marino    : public true_type { };
385*e4b17023SJohn Marino
386*e4b17023SJohn Marino  template<typename _Res, typename... _ArgTypes>
387*e4b17023SJohn Marino    struct is_function<_Res(_ArgTypes...) volatile>
388*e4b17023SJohn Marino    : public true_type { };
389*e4b17023SJohn Marino
390*e4b17023SJohn Marino  template<typename _Res, typename... _ArgTypes>
391*e4b17023SJohn Marino    struct is_function<_Res(_ArgTypes......) volatile>
392*e4b17023SJohn Marino    : public true_type { };
393*e4b17023SJohn Marino
394*e4b17023SJohn Marino  template<typename _Res, typename... _ArgTypes>
395*e4b17023SJohn Marino    struct is_function<_Res(_ArgTypes...) const volatile>
396*e4b17023SJohn Marino    : public true_type { };
397*e4b17023SJohn Marino
398*e4b17023SJohn Marino  template<typename _Res, typename... _ArgTypes>
399*e4b17023SJohn Marino    struct is_function<_Res(_ArgTypes......) const volatile>
400*e4b17023SJohn Marino    : public true_type { };
401*e4b17023SJohn Marino
402*e4b17023SJohn Marino  template<typename>
403*e4b17023SJohn Marino    struct __is_nullptr_t_helper
404*e4b17023SJohn Marino    : public false_type { };
405*e4b17023SJohn Marino
406*e4b17023SJohn Marino  template<>
407*e4b17023SJohn Marino    struct __is_nullptr_t_helper<std::nullptr_t>
408*e4b17023SJohn Marino    : public true_type { };
409*e4b17023SJohn Marino
410*e4b17023SJohn Marino  // __is_nullptr_t (extension).
411*e4b17023SJohn Marino  template<typename _Tp>
412*e4b17023SJohn Marino    struct __is_nullptr_t
413*e4b17023SJohn Marino    : public integral_constant<bool, (__is_nullptr_t_helper<typename
414*e4b17023SJohn Marino				      remove_cv<_Tp>::type>::value)>
415*e4b17023SJohn Marino    { };
416*e4b17023SJohn Marino
417*e4b17023SJohn Marino  // composite type categories.
418*e4b17023SJohn Marino
419*e4b17023SJohn Marino  /// is_reference
420*e4b17023SJohn Marino  template<typename _Tp>
421*e4b17023SJohn Marino    struct is_reference
422*e4b17023SJohn Marino    : public __or_<is_lvalue_reference<_Tp>,
423*e4b17023SJohn Marino                   is_rvalue_reference<_Tp>>::type
424*e4b17023SJohn Marino    { };
425*e4b17023SJohn Marino
426*e4b17023SJohn Marino  /// is_arithmetic
427*e4b17023SJohn Marino  template<typename _Tp>
428*e4b17023SJohn Marino    struct is_arithmetic
429*e4b17023SJohn Marino    : public __or_<is_integral<_Tp>, is_floating_point<_Tp>>::type
430*e4b17023SJohn Marino    { };
431*e4b17023SJohn Marino
432*e4b17023SJohn Marino  /// is_fundamental
433*e4b17023SJohn Marino  template<typename _Tp>
434*e4b17023SJohn Marino    struct is_fundamental
435*e4b17023SJohn Marino    : public __or_<is_arithmetic<_Tp>, is_void<_Tp>>::type
436*e4b17023SJohn Marino    { };
437*e4b17023SJohn Marino
438*e4b17023SJohn Marino  /// is_object
439*e4b17023SJohn Marino  template<typename _Tp>
440*e4b17023SJohn Marino    struct is_object
441*e4b17023SJohn Marino    : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
442*e4b17023SJohn Marino                          is_void<_Tp>>>::type
443*e4b17023SJohn Marino    { };
444*e4b17023SJohn Marino
445*e4b17023SJohn Marino  template<typename>
446*e4b17023SJohn Marino    struct is_member_pointer;
447*e4b17023SJohn Marino
448*e4b17023SJohn Marino  /// is_scalar
449*e4b17023SJohn Marino  template<typename _Tp>
450*e4b17023SJohn Marino    struct is_scalar
451*e4b17023SJohn Marino    : public __or_<is_arithmetic<_Tp>, is_enum<_Tp>, is_pointer<_Tp>,
452*e4b17023SJohn Marino                   is_member_pointer<_Tp>, __is_nullptr_t<_Tp>>::type
453*e4b17023SJohn Marino    { };
454*e4b17023SJohn Marino
455*e4b17023SJohn Marino  /// is_compound
456*e4b17023SJohn Marino  template<typename _Tp>
457*e4b17023SJohn Marino    struct is_compound
458*e4b17023SJohn Marino    : public integral_constant<bool, !is_fundamental<_Tp>::value> { };
459*e4b17023SJohn Marino
460*e4b17023SJohn Marino  template<typename _Tp>
461*e4b17023SJohn Marino    struct __is_member_pointer_helper
462*e4b17023SJohn Marino    : public false_type { };
463*e4b17023SJohn Marino
464*e4b17023SJohn Marino  template<typename _Tp, typename _Cp>
465*e4b17023SJohn Marino    struct __is_member_pointer_helper<_Tp _Cp::*>
466*e4b17023SJohn Marino    : public true_type { };
467*e4b17023SJohn Marino
468*e4b17023SJohn Marino  /// is_member_pointer
469*e4b17023SJohn Marino  template<typename _Tp>
470*e4b17023SJohn Marino    struct is_member_pointer
471*e4b17023SJohn Marino    : public integral_constant<bool, (__is_member_pointer_helper<
472*e4b17023SJohn Marino				      typename remove_cv<_Tp>::type>::value)>
473*e4b17023SJohn Marino    { };
474*e4b17023SJohn Marino
475*e4b17023SJohn Marino  // type properties.
476*e4b17023SJohn Marino
477*e4b17023SJohn Marino  /// is_const
478*e4b17023SJohn Marino  template<typename>
479*e4b17023SJohn Marino    struct is_const
480*e4b17023SJohn Marino    : public false_type { };
481*e4b17023SJohn Marino
482*e4b17023SJohn Marino  template<typename _Tp>
483*e4b17023SJohn Marino    struct is_const<_Tp const>
484*e4b17023SJohn Marino    : public true_type { };
485*e4b17023SJohn Marino
486*e4b17023SJohn Marino  /// is_volatile
487*e4b17023SJohn Marino  template<typename>
488*e4b17023SJohn Marino    struct is_volatile
489*e4b17023SJohn Marino    : public false_type { };
490*e4b17023SJohn Marino
491*e4b17023SJohn Marino  template<typename _Tp>
492*e4b17023SJohn Marino    struct is_volatile<_Tp volatile>
493*e4b17023SJohn Marino    : public true_type { };
494*e4b17023SJohn Marino
495*e4b17023SJohn Marino  /// is_trivial
496*e4b17023SJohn Marino  template<typename _Tp>
497*e4b17023SJohn Marino    struct is_trivial
498*e4b17023SJohn Marino    : public integral_constant<bool, __is_trivial(_Tp)>
499*e4b17023SJohn Marino    { };
500*e4b17023SJohn Marino
501*e4b17023SJohn Marino  // is_trivially_copyable (still unimplemented)
502*e4b17023SJohn Marino
503*e4b17023SJohn Marino  /// is_standard_layout
504*e4b17023SJohn Marino  template<typename _Tp>
505*e4b17023SJohn Marino    struct is_standard_layout
506*e4b17023SJohn Marino    : public integral_constant<bool, __is_standard_layout(_Tp)>
507*e4b17023SJohn Marino    { };
508*e4b17023SJohn Marino
509*e4b17023SJohn Marino  /// is_pod
510*e4b17023SJohn Marino  // Could use is_standard_layout && is_trivial instead of the builtin.
511*e4b17023SJohn Marino  template<typename _Tp>
512*e4b17023SJohn Marino    struct is_pod
513*e4b17023SJohn Marino    : public integral_constant<bool, __is_pod(_Tp)>
514*e4b17023SJohn Marino    { };
515*e4b17023SJohn Marino
516*e4b17023SJohn Marino  /// is_literal_type
517*e4b17023SJohn Marino  template<typename _Tp>
518*e4b17023SJohn Marino    struct is_literal_type
519*e4b17023SJohn Marino    : public integral_constant<bool, __is_literal_type(_Tp)>
520*e4b17023SJohn Marino    { };
521*e4b17023SJohn Marino
522*e4b17023SJohn Marino  /// is_empty
523*e4b17023SJohn Marino  template<typename _Tp>
524*e4b17023SJohn Marino    struct is_empty
525*e4b17023SJohn Marino    : public integral_constant<bool, __is_empty(_Tp)>
526*e4b17023SJohn Marino    { };
527*e4b17023SJohn Marino
528*e4b17023SJohn Marino  /// is_polymorphic
529*e4b17023SJohn Marino  template<typename _Tp>
530*e4b17023SJohn Marino    struct is_polymorphic
531*e4b17023SJohn Marino    : public integral_constant<bool, __is_polymorphic(_Tp)>
532*e4b17023SJohn Marino    { };
533*e4b17023SJohn Marino
534*e4b17023SJohn Marino  /// is_abstract
535*e4b17023SJohn Marino  template<typename _Tp>
536*e4b17023SJohn Marino    struct is_abstract
537*e4b17023SJohn Marino    : public integral_constant<bool, __is_abstract(_Tp)>
538*e4b17023SJohn Marino    { };
539*e4b17023SJohn Marino
540*e4b17023SJohn Marino  template<typename _Tp,
541*e4b17023SJohn Marino	   bool = is_integral<_Tp>::value,
542*e4b17023SJohn Marino	   bool = is_floating_point<_Tp>::value>
543*e4b17023SJohn Marino    struct __is_signed_helper
544*e4b17023SJohn Marino    : public false_type { };
545*e4b17023SJohn Marino
546*e4b17023SJohn Marino  template<typename _Tp>
547*e4b17023SJohn Marino    struct __is_signed_helper<_Tp, false, true>
548*e4b17023SJohn Marino    : public true_type { };
549*e4b17023SJohn Marino
550*e4b17023SJohn Marino  template<typename _Tp>
551*e4b17023SJohn Marino    struct __is_signed_helper<_Tp, true, false>
552*e4b17023SJohn Marino    : public integral_constant<bool, static_cast<bool>(_Tp(-1) < _Tp(0))>
553*e4b17023SJohn Marino    { };
554*e4b17023SJohn Marino
555*e4b17023SJohn Marino  /// is_signed
556*e4b17023SJohn Marino  template<typename _Tp>
557*e4b17023SJohn Marino    struct is_signed
558*e4b17023SJohn Marino    : public integral_constant<bool, __is_signed_helper<_Tp>::value>
559*e4b17023SJohn Marino    { };
560*e4b17023SJohn Marino
561*e4b17023SJohn Marino  /// is_unsigned
562*e4b17023SJohn Marino  template<typename _Tp>
563*e4b17023SJohn Marino    struct is_unsigned
564*e4b17023SJohn Marino    : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type
565*e4b17023SJohn Marino    { };
566*e4b17023SJohn Marino
567*e4b17023SJohn Marino
568*e4b17023SJohn Marino  // destructible and constructible type properties
569*e4b17023SJohn Marino
570*e4b17023SJohn Marino  template<typename>
571*e4b17023SJohn Marino    struct add_rvalue_reference;
572*e4b17023SJohn Marino
573*e4b17023SJohn Marino  /**
574*e4b17023SJohn Marino   *  @brief  Utility to simplify expressions used in unevaluated operands
575*e4b17023SJohn Marino   *  @ingroup utilities
576*e4b17023SJohn Marino   */
577*e4b17023SJohn Marino  template<typename _Tp>
578*e4b17023SJohn Marino    typename add_rvalue_reference<_Tp>::type declval() noexcept;
579*e4b17023SJohn Marino
580*e4b17023SJohn Marino  template<typename, unsigned = 0>
581*e4b17023SJohn Marino    struct extent;
582*e4b17023SJohn Marino
583*e4b17023SJohn Marino  template<typename>
584*e4b17023SJohn Marino    struct remove_all_extents;
585*e4b17023SJohn Marino
586*e4b17023SJohn Marino  template<typename _Tp>
587*e4b17023SJohn Marino    struct __is_array_known_bounds
588*e4b17023SJohn Marino    : public integral_constant<bool, (extent<_Tp>::value > 0)>
589*e4b17023SJohn Marino    { };
590*e4b17023SJohn Marino
591*e4b17023SJohn Marino  template<typename _Tp>
592*e4b17023SJohn Marino    struct __is_array_unknown_bounds
593*e4b17023SJohn Marino    : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>::type
594*e4b17023SJohn Marino    { };
595*e4b17023SJohn Marino
596*e4b17023SJohn Marino  // In N3290 is_destructible does not say anything about function
597*e4b17023SJohn Marino  // types and abstract types, see LWG 2049. This implementation
598*e4b17023SJohn Marino  // describes function types as trivially nothrow destructible and
599*e4b17023SJohn Marino  // abstract types as destructible, iff the  explicit destructor
600*e4b17023SJohn Marino  // call expression is wellformed.
601*e4b17023SJohn Marino  struct __do_is_destructible_impl_1
602*e4b17023SJohn Marino  {
603*e4b17023SJohn Marino    template<typename _Up>
604*e4b17023SJohn Marino      struct __w { _Up __u; };
605*e4b17023SJohn Marino
606*e4b17023SJohn Marino    template<typename _Tp, typename
607*e4b17023SJohn Marino             = decltype(declval<__w<_Tp>&>().~__w<_Tp>())>
608*e4b17023SJohn Marino      static true_type __test(int);
609*e4b17023SJohn Marino
610*e4b17023SJohn Marino    template<typename>
611*e4b17023SJohn Marino      static false_type __test(...);
612*e4b17023SJohn Marino  };
613*e4b17023SJohn Marino
614*e4b17023SJohn Marino  template<typename _Tp>
615*e4b17023SJohn Marino    struct __is_destructible_impl_1
616*e4b17023SJohn Marino    : public __do_is_destructible_impl_1
617*e4b17023SJohn Marino    {
618*e4b17023SJohn Marino      typedef decltype(__test<_Tp>(0)) type;
619*e4b17023SJohn Marino    };
620*e4b17023SJohn Marino
621*e4b17023SJohn Marino  // Special implementation for abstract types
622*e4b17023SJohn Marino  struct __do_is_destructible_impl_2
623*e4b17023SJohn Marino  {
624*e4b17023SJohn Marino    template<typename _Tp, typename = decltype(declval<_Tp&>().~_Tp())>
625*e4b17023SJohn Marino      static true_type __test(int);
626*e4b17023SJohn Marino
627*e4b17023SJohn Marino    template<typename>
628*e4b17023SJohn Marino      static false_type __test(...);
629*e4b17023SJohn Marino  };
630*e4b17023SJohn Marino
631*e4b17023SJohn Marino  template<typename _Tp>
632*e4b17023SJohn Marino    struct __is_destructible_impl_2
633*e4b17023SJohn Marino    : public __do_is_destructible_impl_2
634*e4b17023SJohn Marino    {
635*e4b17023SJohn Marino      typedef decltype(__test<_Tp>(0)) type;
636*e4b17023SJohn Marino    };
637*e4b17023SJohn Marino
638*e4b17023SJohn Marino  template<typename _Tp,
639*e4b17023SJohn Marino           bool = __or_<is_void<_Tp>,
640*e4b17023SJohn Marino                        __is_array_unknown_bounds<_Tp>>::value,
641*e4b17023SJohn Marino           bool = __or_<is_reference<_Tp>, is_function<_Tp>>::value>
642*e4b17023SJohn Marino    struct __is_destructible_safe;
643*e4b17023SJohn Marino
644*e4b17023SJohn Marino  template<typename _Tp>
645*e4b17023SJohn Marino    struct __is_destructible_safe<_Tp, false, false>
646*e4b17023SJohn Marino    : public conditional<is_abstract<_Tp>::value,
647*e4b17023SJohn Marino			 __is_destructible_impl_2<_Tp>,
648*e4b17023SJohn Marino                         __is_destructible_impl_1<_Tp>>::type::type
649*e4b17023SJohn Marino    { };
650*e4b17023SJohn Marino
651*e4b17023SJohn Marino  template<typename _Tp>
652*e4b17023SJohn Marino    struct __is_destructible_safe<_Tp, true, false>
653*e4b17023SJohn Marino    : public false_type { };
654*e4b17023SJohn Marino
655*e4b17023SJohn Marino  template<typename _Tp>
656*e4b17023SJohn Marino    struct __is_destructible_safe<_Tp, false, true>
657*e4b17023SJohn Marino    : public true_type { };
658*e4b17023SJohn Marino
659*e4b17023SJohn Marino  /// is_destructible
660*e4b17023SJohn Marino  template<typename _Tp>
661*e4b17023SJohn Marino    struct is_destructible
662*e4b17023SJohn Marino    : public integral_constant<bool, (__is_destructible_safe<_Tp>::value)>
663*e4b17023SJohn Marino    { };
664*e4b17023SJohn Marino
665*e4b17023SJohn Marino  struct __do_is_default_constructible_impl
666*e4b17023SJohn Marino  {
667*e4b17023SJohn Marino    template<typename _Tp, typename = decltype(_Tp())>
668*e4b17023SJohn Marino      static true_type __test(int);
669*e4b17023SJohn Marino
670*e4b17023SJohn Marino    template<typename>
671*e4b17023SJohn Marino      static false_type __test(...);
672*e4b17023SJohn Marino  };
673*e4b17023SJohn Marino
674*e4b17023SJohn Marino  template<typename _Tp>
675*e4b17023SJohn Marino    struct __is_default_constructible_impl
676*e4b17023SJohn Marino    : public __do_is_default_constructible_impl
677*e4b17023SJohn Marino    {
678*e4b17023SJohn Marino      typedef decltype(__test<_Tp>(0)) type;
679*e4b17023SJohn Marino    };
680*e4b17023SJohn Marino
681*e4b17023SJohn Marino  template<typename _Tp>
682*e4b17023SJohn Marino    struct __is_default_constructible_atom
683*e4b17023SJohn Marino    : public __and_<__not_<is_void<_Tp>>,
684*e4b17023SJohn Marino                    __is_default_constructible_impl<_Tp>>::type
685*e4b17023SJohn Marino    { };
686*e4b17023SJohn Marino
687*e4b17023SJohn Marino  template<typename _Tp, bool = is_array<_Tp>::value>
688*e4b17023SJohn Marino    struct __is_default_constructible_safe;
689*e4b17023SJohn Marino
690*e4b17023SJohn Marino  // The following technique is a workaround for a current core language
691*e4b17023SJohn Marino  // restriction, which does not allow for array types to occur in
692*e4b17023SJohn Marino  // functional casts of the form T().  Complete arrays can be default-
693*e4b17023SJohn Marino  // constructed, if the element type is default-constructible, but
694*e4b17023SJohn Marino  // arrays with unknown bounds are not.
695*e4b17023SJohn Marino  template<typename _Tp>
696*e4b17023SJohn Marino    struct __is_default_constructible_safe<_Tp, true>
697*e4b17023SJohn Marino    : public __and_<__is_array_known_bounds<_Tp>,
698*e4b17023SJohn Marino		    __is_default_constructible_atom<typename
699*e4b17023SJohn Marino                      remove_all_extents<_Tp>::type>>::type
700*e4b17023SJohn Marino    { };
701*e4b17023SJohn Marino
702*e4b17023SJohn Marino  template<typename _Tp>
703*e4b17023SJohn Marino    struct __is_default_constructible_safe<_Tp, false>
704*e4b17023SJohn Marino    : public __is_default_constructible_atom<_Tp>::type
705*e4b17023SJohn Marino    { };
706*e4b17023SJohn Marino
707*e4b17023SJohn Marino  /// is_default_constructible
708*e4b17023SJohn Marino  template<typename _Tp>
709*e4b17023SJohn Marino    struct is_default_constructible
710*e4b17023SJohn Marino    : public integral_constant<bool, (__is_default_constructible_safe<
711*e4b17023SJohn Marino				      _Tp>::value)>
712*e4b17023SJohn Marino    { };
713*e4b17023SJohn Marino
714*e4b17023SJohn Marino
715*e4b17023SJohn Marino  // Implementation of is_constructible.
716*e4b17023SJohn Marino
717*e4b17023SJohn Marino  // The hardest part of this trait is the binary direct-initialization
718*e4b17023SJohn Marino  // case, because we hit into a functional cast of the form T(arg).
719*e4b17023SJohn Marino  // This implementation uses different strategies depending on the
720*e4b17023SJohn Marino  // target type to reduce the test overhead as much as possible:
721*e4b17023SJohn Marino  //
722*e4b17023SJohn Marino  // a) For a reference target type, we use a static_cast expression
723*e4b17023SJohn Marino  //    modulo its extra cases.
724*e4b17023SJohn Marino  //
725*e4b17023SJohn Marino  // b) For a non-reference target type we use a ::new expression.
726*e4b17023SJohn Marino  struct __do_is_static_castable_impl
727*e4b17023SJohn Marino  {
728*e4b17023SJohn Marino    template<typename _From, typename _To, typename
729*e4b17023SJohn Marino             = decltype(static_cast<_To>(declval<_From>()))>
730*e4b17023SJohn Marino      static true_type __test(int);
731*e4b17023SJohn Marino
732*e4b17023SJohn Marino    template<typename, typename>
733*e4b17023SJohn Marino      static false_type __test(...);
734*e4b17023SJohn Marino  };
735*e4b17023SJohn Marino
736*e4b17023SJohn Marino  template<typename _From, typename _To>
737*e4b17023SJohn Marino    struct __is_static_castable_impl
738*e4b17023SJohn Marino    : public __do_is_static_castable_impl
739*e4b17023SJohn Marino    {
740*e4b17023SJohn Marino      typedef decltype(__test<_From, _To>(0)) type;
741*e4b17023SJohn Marino    };
742*e4b17023SJohn Marino
743*e4b17023SJohn Marino  template<typename _From, typename _To>
744*e4b17023SJohn Marino    struct __is_static_castable_safe
745*e4b17023SJohn Marino    : public __is_static_castable_impl<_From, _To>::type
746*e4b17023SJohn Marino    { };
747*e4b17023SJohn Marino
748*e4b17023SJohn Marino  // __is_static_castable
749*e4b17023SJohn Marino  template<typename _From, typename _To>
750*e4b17023SJohn Marino    struct __is_static_castable
751*e4b17023SJohn Marino    : public integral_constant<bool, (__is_static_castable_safe<
752*e4b17023SJohn Marino				      _From, _To>::value)>
753*e4b17023SJohn Marino    { };
754*e4b17023SJohn Marino
755*e4b17023SJohn Marino  // Implementation for non-reference types. To meet the proper
756*e4b17023SJohn Marino  // variable definition semantics, we also need to test for
757*e4b17023SJohn Marino  // is_destructible in this case.
758*e4b17023SJohn Marino  // This form should be simplified by a single expression:
759*e4b17023SJohn Marino  // ::delete ::new _Tp(declval<_Arg>()), see c++/51222.
760*e4b17023SJohn Marino  struct __do_is_direct_constructible_impl
761*e4b17023SJohn Marino  {
762*e4b17023SJohn Marino    template<typename _Tp, typename _Arg, typename
763*e4b17023SJohn Marino	     = decltype(::new _Tp(declval<_Arg>()))>
764*e4b17023SJohn Marino      static true_type __test(int);
765*e4b17023SJohn Marino
766*e4b17023SJohn Marino    template<typename, typename>
767*e4b17023SJohn Marino      static false_type __test(...);
768*e4b17023SJohn Marino  };
769*e4b17023SJohn Marino
770*e4b17023SJohn Marino  template<typename _Tp, typename _Arg>
771*e4b17023SJohn Marino    struct __is_direct_constructible_impl
772*e4b17023SJohn Marino    : public __do_is_direct_constructible_impl
773*e4b17023SJohn Marino    {
774*e4b17023SJohn Marino      typedef decltype(__test<_Tp, _Arg>(0)) type;
775*e4b17023SJohn Marino    };
776*e4b17023SJohn Marino
777*e4b17023SJohn Marino  template<typename _Tp, typename _Arg>
778*e4b17023SJohn Marino    struct __is_direct_constructible_new_safe
779*e4b17023SJohn Marino    : public __and_<is_destructible<_Tp>,
780*e4b17023SJohn Marino                    __is_direct_constructible_impl<_Tp, _Arg>>::type
781*e4b17023SJohn Marino    { };
782*e4b17023SJohn Marino
783*e4b17023SJohn Marino  template<typename, typename>
784*e4b17023SJohn Marino    struct is_same;
785*e4b17023SJohn Marino
786*e4b17023SJohn Marino  template<typename, typename>
787*e4b17023SJohn Marino    struct is_base_of;
788*e4b17023SJohn Marino
789*e4b17023SJohn Marino  template<typename>
790*e4b17023SJohn Marino    struct remove_reference;
791*e4b17023SJohn Marino
792*e4b17023SJohn Marino  template<typename _From, typename _To, bool
793*e4b17023SJohn Marino           = __not_<__or_<is_void<_From>,
794*e4b17023SJohn Marino                          is_function<_From>>>::value>
795*e4b17023SJohn Marino    struct __is_base_to_derived_ref;
796*e4b17023SJohn Marino
797*e4b17023SJohn Marino  // Detect whether we have a downcast situation during
798*e4b17023SJohn Marino  // reference binding.
799*e4b17023SJohn Marino  template<typename _From, typename _To>
800*e4b17023SJohn Marino    struct __is_base_to_derived_ref<_From, _To, true>
801*e4b17023SJohn Marino    {
802*e4b17023SJohn Marino      typedef typename remove_cv<typename remove_reference<_From
803*e4b17023SJohn Marino        >::type>::type __src_t;
804*e4b17023SJohn Marino      typedef typename remove_cv<typename remove_reference<_To
805*e4b17023SJohn Marino        >::type>::type __dst_t;
806*e4b17023SJohn Marino      typedef __and_<__not_<is_same<__src_t, __dst_t>>,
807*e4b17023SJohn Marino		     is_base_of<__src_t, __dst_t>> type;
808*e4b17023SJohn Marino      static constexpr bool value = type::value;
809*e4b17023SJohn Marino    };
810*e4b17023SJohn Marino
811*e4b17023SJohn Marino  template<typename _From, typename _To>
812*e4b17023SJohn Marino    struct __is_base_to_derived_ref<_From, _To, false>
813*e4b17023SJohn Marino    : public false_type
814*e4b17023SJohn Marino    { };
815*e4b17023SJohn Marino
816*e4b17023SJohn Marino  template<typename _From, typename _To, bool
817*e4b17023SJohn Marino           = __and_<is_lvalue_reference<_From>,
818*e4b17023SJohn Marino                    is_rvalue_reference<_To>>::value>
819*e4b17023SJohn Marino    struct __is_lvalue_to_rvalue_ref;
820*e4b17023SJohn Marino
821*e4b17023SJohn Marino  // Detect whether we have an lvalue of non-function type
822*e4b17023SJohn Marino  // bound to a reference-compatible rvalue-reference.
823*e4b17023SJohn Marino  template<typename _From, typename _To>
824*e4b17023SJohn Marino    struct __is_lvalue_to_rvalue_ref<_From, _To, true>
825*e4b17023SJohn Marino    {
826*e4b17023SJohn Marino      typedef typename remove_cv<typename remove_reference<
827*e4b17023SJohn Marino        _From>::type>::type __src_t;
828*e4b17023SJohn Marino      typedef typename remove_cv<typename remove_reference<
829*e4b17023SJohn Marino        _To>::type>::type __dst_t;
830*e4b17023SJohn Marino      typedef __and_<__not_<is_function<__src_t>>,
831*e4b17023SJohn Marino        __or_<is_same<__src_t, __dst_t>,
832*e4b17023SJohn Marino		    is_base_of<__dst_t, __src_t>>> type;
833*e4b17023SJohn Marino      static constexpr bool value = type::value;
834*e4b17023SJohn Marino    };
835*e4b17023SJohn Marino
836*e4b17023SJohn Marino  template<typename _From, typename _To>
837*e4b17023SJohn Marino    struct __is_lvalue_to_rvalue_ref<_From, _To, false>
838*e4b17023SJohn Marino    : public false_type
839*e4b17023SJohn Marino    { };
840*e4b17023SJohn Marino
841*e4b17023SJohn Marino  // Here we handle direct-initialization to a reference type as
842*e4b17023SJohn Marino  // equivalent to a static_cast modulo overshooting conversions.
843*e4b17023SJohn Marino  // These are restricted to the following conversions:
844*e4b17023SJohn Marino  //    a) A base class value to a derived class reference
845*e4b17023SJohn Marino  //    b) An lvalue to an rvalue-reference of reference-compatible
846*e4b17023SJohn Marino  //       types that are not functions
847*e4b17023SJohn Marino  template<typename _Tp, typename _Arg>
848*e4b17023SJohn Marino    struct __is_direct_constructible_ref_cast
849*e4b17023SJohn Marino    : public __and_<__is_static_castable<_Arg, _Tp>,
850*e4b17023SJohn Marino                    __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>,
851*e4b17023SJohn Marino                                 __is_lvalue_to_rvalue_ref<_Arg, _Tp>
852*e4b17023SJohn Marino                   >>>::type
853*e4b17023SJohn Marino    { };
854*e4b17023SJohn Marino
855*e4b17023SJohn Marino  template<typename _Tp, typename _Arg>
856*e4b17023SJohn Marino    struct __is_direct_constructible_new
857*e4b17023SJohn Marino    : public conditional<is_reference<_Tp>::value,
858*e4b17023SJohn Marino			 __is_direct_constructible_ref_cast<_Tp, _Arg>,
859*e4b17023SJohn Marino			 __is_direct_constructible_new_safe<_Tp, _Arg>
860*e4b17023SJohn Marino			 >::type
861*e4b17023SJohn Marino    { };
862*e4b17023SJohn Marino
863*e4b17023SJohn Marino  template<typename _Tp, typename _Arg>
864*e4b17023SJohn Marino    struct __is_direct_constructible
865*e4b17023SJohn Marino    : public integral_constant<bool, (__is_direct_constructible_new<
866*e4b17023SJohn Marino				      _Tp, _Arg>::value)>
867*e4b17023SJohn Marino    { };
868*e4b17023SJohn Marino
869*e4b17023SJohn Marino  // Since default-construction and binary direct-initialization have
870*e4b17023SJohn Marino  // been handled separately, the implementation of the remaining
871*e4b17023SJohn Marino  // n-ary construction cases is rather straightforward. We can use
872*e4b17023SJohn Marino  // here a functional cast, because array types are excluded anyway
873*e4b17023SJohn Marino  // and this form is never interpreted as a C cast.
874*e4b17023SJohn Marino  struct __do_is_nary_constructible_impl
875*e4b17023SJohn Marino  {
876*e4b17023SJohn Marino    template<typename _Tp, typename... _Args, typename
877*e4b17023SJohn Marino             = decltype(_Tp(declval<_Args>()...))>
878*e4b17023SJohn Marino      static true_type __test(int);
879*e4b17023SJohn Marino
880*e4b17023SJohn Marino    template<typename, typename...>
881*e4b17023SJohn Marino      static false_type __test(...);
882*e4b17023SJohn Marino  };
883*e4b17023SJohn Marino
884*e4b17023SJohn Marino  template<typename _Tp, typename... _Args>
885*e4b17023SJohn Marino    struct __is_nary_constructible_impl
886*e4b17023SJohn Marino    : public __do_is_nary_constructible_impl
887*e4b17023SJohn Marino    {
888*e4b17023SJohn Marino      typedef decltype(__test<_Tp, _Args...>(0)) type;
889*e4b17023SJohn Marino    };
890*e4b17023SJohn Marino
891*e4b17023SJohn Marino  template<typename _Tp, typename... _Args>
892*e4b17023SJohn Marino    struct __is_nary_constructible
893*e4b17023SJohn Marino    : public __is_nary_constructible_impl<_Tp, _Args...>::type
894*e4b17023SJohn Marino    {
895*e4b17023SJohn Marino      static_assert(sizeof...(_Args) > 1,
896*e4b17023SJohn Marino                    "Only useful for > 1 arguments");
897*e4b17023SJohn Marino    };
898*e4b17023SJohn Marino
899*e4b17023SJohn Marino  template<typename _Tp, typename... _Args>
900*e4b17023SJohn Marino    struct __is_constructible_impl
901*e4b17023SJohn Marino    : public __is_nary_constructible<_Tp, _Args...>
902*e4b17023SJohn Marino    { };
903*e4b17023SJohn Marino
904*e4b17023SJohn Marino  template<typename _Tp, typename _Arg>
905*e4b17023SJohn Marino    struct __is_constructible_impl<_Tp, _Arg>
906*e4b17023SJohn Marino    : public __is_direct_constructible<_Tp, _Arg>
907*e4b17023SJohn Marino    { };
908*e4b17023SJohn Marino
909*e4b17023SJohn Marino  template<typename _Tp>
910*e4b17023SJohn Marino    struct __is_constructible_impl<_Tp>
911*e4b17023SJohn Marino    : public is_default_constructible<_Tp>
912*e4b17023SJohn Marino    { };
913*e4b17023SJohn Marino
914*e4b17023SJohn Marino  /// is_constructible
915*e4b17023SJohn Marino  template<typename _Tp, typename... _Args>
916*e4b17023SJohn Marino    struct is_constructible
917*e4b17023SJohn Marino    : public integral_constant<bool, (__is_constructible_impl<_Tp,
918*e4b17023SJohn Marino				      _Args...>::value)>
919*e4b17023SJohn Marino    { };
920*e4b17023SJohn Marino
921*e4b17023SJohn Marino  template<typename _Tp, bool = is_void<_Tp>::value>
922*e4b17023SJohn Marino    struct __is_copy_constructible_impl;
923*e4b17023SJohn Marino
924*e4b17023SJohn Marino  template<typename _Tp>
925*e4b17023SJohn Marino    struct __is_copy_constructible_impl<_Tp, true>
926*e4b17023SJohn Marino    : public false_type { };
927*e4b17023SJohn Marino
928*e4b17023SJohn Marino  template<typename _Tp>
929*e4b17023SJohn Marino    struct __is_copy_constructible_impl<_Tp, false>
930*e4b17023SJohn Marino    : public is_constructible<_Tp, const _Tp&>
931*e4b17023SJohn Marino    { };
932*e4b17023SJohn Marino
933*e4b17023SJohn Marino  /// is_copy_constructible
934*e4b17023SJohn Marino  template<typename _Tp>
935*e4b17023SJohn Marino    struct is_copy_constructible
936*e4b17023SJohn Marino    : public __is_copy_constructible_impl<_Tp>
937*e4b17023SJohn Marino    { };
938*e4b17023SJohn Marino
939*e4b17023SJohn Marino  template<typename _Tp, bool = is_void<_Tp>::value>
940*e4b17023SJohn Marino    struct __is_move_constructible_impl;
941*e4b17023SJohn Marino
942*e4b17023SJohn Marino  template<typename _Tp>
943*e4b17023SJohn Marino    struct __is_move_constructible_impl<_Tp, true>
944*e4b17023SJohn Marino    : public false_type { };
945*e4b17023SJohn Marino
946*e4b17023SJohn Marino  template<typename _Tp>
947*e4b17023SJohn Marino    struct __is_move_constructible_impl<_Tp, false>
948*e4b17023SJohn Marino    : public is_constructible<_Tp, _Tp&&>
949*e4b17023SJohn Marino    { };
950*e4b17023SJohn Marino
951*e4b17023SJohn Marino  /// is_move_constructible
952*e4b17023SJohn Marino  template<typename _Tp>
953*e4b17023SJohn Marino    struct is_move_constructible
954*e4b17023SJohn Marino    : public __is_move_constructible_impl<_Tp>
955*e4b17023SJohn Marino    { };
956*e4b17023SJohn Marino
957*e4b17023SJohn Marino  template<typename _Tp>
958*e4b17023SJohn Marino    struct __is_nt_default_constructible_atom
959*e4b17023SJohn Marino    : public integral_constant<bool, noexcept(_Tp())>
960*e4b17023SJohn Marino    { };
961*e4b17023SJohn Marino
962*e4b17023SJohn Marino  template<typename _Tp, bool = is_array<_Tp>::value>
963*e4b17023SJohn Marino    struct __is_nt_default_constructible_impl;
964*e4b17023SJohn Marino
965*e4b17023SJohn Marino  template<typename _Tp>
966*e4b17023SJohn Marino    struct __is_nt_default_constructible_impl<_Tp, true>
967*e4b17023SJohn Marino    : public __and_<__is_array_known_bounds<_Tp>,
968*e4b17023SJohn Marino		    __is_nt_default_constructible_atom<typename
969*e4b17023SJohn Marino                      remove_all_extents<_Tp>::type>>::type
970*e4b17023SJohn Marino    { };
971*e4b17023SJohn Marino
972*e4b17023SJohn Marino  template<typename _Tp>
973*e4b17023SJohn Marino    struct __is_nt_default_constructible_impl<_Tp, false>
974*e4b17023SJohn Marino    : public __is_nt_default_constructible_atom<_Tp>
975*e4b17023SJohn Marino    { };
976*e4b17023SJohn Marino
977*e4b17023SJohn Marino  /// is_nothrow_default_constructible
978*e4b17023SJohn Marino  template<typename _Tp>
979*e4b17023SJohn Marino    struct is_nothrow_default_constructible
980*e4b17023SJohn Marino    : public __and_<is_default_constructible<_Tp>,
981*e4b17023SJohn Marino                    __is_nt_default_constructible_impl<_Tp>>::type
982*e4b17023SJohn Marino    { };
983*e4b17023SJohn Marino
984*e4b17023SJohn Marino  template<typename _Tp, typename... _Args>
985*e4b17023SJohn Marino    struct __is_nt_constructible_impl
986*e4b17023SJohn Marino    : public integral_constant<bool, noexcept(_Tp(declval<_Args>()...))>
987*e4b17023SJohn Marino    { };
988*e4b17023SJohn Marino
989*e4b17023SJohn Marino  template<typename _Tp, typename _Arg>
990*e4b17023SJohn Marino    struct __is_nt_constructible_impl<_Tp, _Arg>
991*e4b17023SJohn Marino    : public integral_constant<bool,
992*e4b17023SJohn Marino                               noexcept(static_cast<_Tp>(declval<_Arg>()))>
993*e4b17023SJohn Marino    { };
994*e4b17023SJohn Marino
995*e4b17023SJohn Marino  template<typename _Tp>
996*e4b17023SJohn Marino    struct __is_nt_constructible_impl<_Tp>
997*e4b17023SJohn Marino    : public is_nothrow_default_constructible<_Tp>
998*e4b17023SJohn Marino    { };
999*e4b17023SJohn Marino
1000*e4b17023SJohn Marino  /// is_nothrow_constructible
1001*e4b17023SJohn Marino  template<typename _Tp, typename... _Args>
1002*e4b17023SJohn Marino    struct is_nothrow_constructible
1003*e4b17023SJohn Marino    : public __and_<is_constructible<_Tp, _Args...>,
1004*e4b17023SJohn Marino		    __is_nt_constructible_impl<_Tp, _Args...>>::type
1005*e4b17023SJohn Marino    { };
1006*e4b17023SJohn Marino
1007*e4b17023SJohn Marino  template<typename _Tp, bool = is_void<_Tp>::value>
1008*e4b17023SJohn Marino    struct __is_nothrow_copy_constructible_impl;
1009*e4b17023SJohn Marino
1010*e4b17023SJohn Marino  template<typename _Tp>
1011*e4b17023SJohn Marino    struct __is_nothrow_copy_constructible_impl<_Tp, true>
1012*e4b17023SJohn Marino    : public false_type { };
1013*e4b17023SJohn Marino
1014*e4b17023SJohn Marino  template<typename _Tp>
1015*e4b17023SJohn Marino    struct __is_nothrow_copy_constructible_impl<_Tp, false>
1016*e4b17023SJohn Marino    : public is_nothrow_constructible<_Tp, const _Tp&>
1017*e4b17023SJohn Marino    { };
1018*e4b17023SJohn Marino
1019*e4b17023SJohn Marino  /// is_nothrow_copy_constructible
1020*e4b17023SJohn Marino  template<typename _Tp>
1021*e4b17023SJohn Marino    struct is_nothrow_copy_constructible
1022*e4b17023SJohn Marino    : public __is_nothrow_copy_constructible_impl<_Tp>
1023*e4b17023SJohn Marino    { };
1024*e4b17023SJohn Marino
1025*e4b17023SJohn Marino  template<typename _Tp, bool = is_void<_Tp>::value>
1026*e4b17023SJohn Marino    struct __is_nothrow_move_constructible_impl;
1027*e4b17023SJohn Marino
1028*e4b17023SJohn Marino  template<typename _Tp>
1029*e4b17023SJohn Marino    struct __is_nothrow_move_constructible_impl<_Tp, true>
1030*e4b17023SJohn Marino    : public false_type { };
1031*e4b17023SJohn Marino
1032*e4b17023SJohn Marino  template<typename _Tp>
1033*e4b17023SJohn Marino    struct __is_nothrow_move_constructible_impl<_Tp, false>
1034*e4b17023SJohn Marino    : public is_nothrow_constructible<_Tp, _Tp&&>
1035*e4b17023SJohn Marino    { };
1036*e4b17023SJohn Marino
1037*e4b17023SJohn Marino  /// is_nothrow_move_constructible
1038*e4b17023SJohn Marino  template<typename _Tp>
1039*e4b17023SJohn Marino    struct is_nothrow_move_constructible
1040*e4b17023SJohn Marino    : public __is_nothrow_move_constructible_impl<_Tp>
1041*e4b17023SJohn Marino    { };
1042*e4b17023SJohn Marino
1043*e4b17023SJohn Marino  template<typename _Tp, typename _Up>
1044*e4b17023SJohn Marino    class __is_assignable_helper
1045*e4b17023SJohn Marino    : public __sfinae_types
1046*e4b17023SJohn Marino    {
1047*e4b17023SJohn Marino      template<typename _Tp1, typename _Up1>
1048*e4b17023SJohn Marino        static decltype(declval<_Tp1>() = declval<_Up1>(), __one())
1049*e4b17023SJohn Marino	__test(int);
1050*e4b17023SJohn Marino
1051*e4b17023SJohn Marino      template<typename, typename>
1052*e4b17023SJohn Marino        static __two __test(...);
1053*e4b17023SJohn Marino
1054*e4b17023SJohn Marino    public:
1055*e4b17023SJohn Marino      static constexpr bool value = sizeof(__test<_Tp, _Up>(0)) == 1;
1056*e4b17023SJohn Marino    };
1057*e4b17023SJohn Marino
1058*e4b17023SJohn Marino  /// is_assignable
1059*e4b17023SJohn Marino  template<typename _Tp, typename _Up>
1060*e4b17023SJohn Marino    struct is_assignable
1061*e4b17023SJohn Marino    : public integral_constant<bool,
1062*e4b17023SJohn Marino                               __is_assignable_helper<_Tp, _Up>::value>
1063*e4b17023SJohn Marino    { };
1064*e4b17023SJohn Marino
1065*e4b17023SJohn Marino  template<typename _Tp, bool = is_void<_Tp>::value>
1066*e4b17023SJohn Marino    struct __is_copy_assignable_impl;
1067*e4b17023SJohn Marino
1068*e4b17023SJohn Marino  template<typename _Tp>
1069*e4b17023SJohn Marino    struct __is_copy_assignable_impl<_Tp, true>
1070*e4b17023SJohn Marino    : public false_type { };
1071*e4b17023SJohn Marino
1072*e4b17023SJohn Marino  template<typename _Tp>
1073*e4b17023SJohn Marino    struct __is_copy_assignable_impl<_Tp, false>
1074*e4b17023SJohn Marino    : public is_assignable<_Tp&, const _Tp&>
1075*e4b17023SJohn Marino    { };
1076*e4b17023SJohn Marino
1077*e4b17023SJohn Marino  /// is_copy_assignable
1078*e4b17023SJohn Marino  template<typename _Tp>
1079*e4b17023SJohn Marino    struct is_copy_assignable
1080*e4b17023SJohn Marino    : public __is_copy_assignable_impl<_Tp>
1081*e4b17023SJohn Marino    { };
1082*e4b17023SJohn Marino
1083*e4b17023SJohn Marino  template<typename _Tp, bool = is_void<_Tp>::value>
1084*e4b17023SJohn Marino    struct __is_move_assignable_impl;
1085*e4b17023SJohn Marino
1086*e4b17023SJohn Marino  template<typename _Tp>
1087*e4b17023SJohn Marino    struct __is_move_assignable_impl<_Tp, true>
1088*e4b17023SJohn Marino    : public false_type { };
1089*e4b17023SJohn Marino
1090*e4b17023SJohn Marino  template<typename _Tp>
1091*e4b17023SJohn Marino    struct __is_move_assignable_impl<_Tp, false>
1092*e4b17023SJohn Marino    : public is_assignable<_Tp&, _Tp&&>
1093*e4b17023SJohn Marino    { };
1094*e4b17023SJohn Marino
1095*e4b17023SJohn Marino  /// is_move_assignable
1096*e4b17023SJohn Marino  template<typename _Tp>
1097*e4b17023SJohn Marino    struct is_move_assignable
1098*e4b17023SJohn Marino    : public __is_move_assignable_impl<_Tp>
1099*e4b17023SJohn Marino    { };
1100*e4b17023SJohn Marino
1101*e4b17023SJohn Marino  template<typename _Tp, typename _Up>
1102*e4b17023SJohn Marino    struct __is_nt_assignable_impl
1103*e4b17023SJohn Marino    : public integral_constant<bool, noexcept(declval<_Tp>() = declval<_Up>())>
1104*e4b17023SJohn Marino    { };
1105*e4b17023SJohn Marino
1106*e4b17023SJohn Marino  /// is_nothrow_assignable
1107*e4b17023SJohn Marino  template<typename _Tp, typename _Up>
1108*e4b17023SJohn Marino    struct is_nothrow_assignable
1109*e4b17023SJohn Marino    : public __and_<is_assignable<_Tp, _Up>,
1110*e4b17023SJohn Marino		    __is_nt_assignable_impl<_Tp, _Up>>::type
1111*e4b17023SJohn Marino    { };
1112*e4b17023SJohn Marino
1113*e4b17023SJohn Marino  template<typename _Tp, bool = is_void<_Tp>::value>
1114*e4b17023SJohn Marino    struct __is_nt_copy_assignable_impl;
1115*e4b17023SJohn Marino
1116*e4b17023SJohn Marino  template<typename _Tp>
1117*e4b17023SJohn Marino    struct __is_nt_copy_assignable_impl<_Tp, true>
1118*e4b17023SJohn Marino    : public false_type { };
1119*e4b17023SJohn Marino
1120*e4b17023SJohn Marino  template<typename _Tp>
1121*e4b17023SJohn Marino    struct __is_nt_copy_assignable_impl<_Tp, false>
1122*e4b17023SJohn Marino    : public is_nothrow_assignable<_Tp&, const _Tp&>
1123*e4b17023SJohn Marino    { };
1124*e4b17023SJohn Marino
1125*e4b17023SJohn Marino  /// is_nothrow_copy_assignable
1126*e4b17023SJohn Marino  template<typename _Tp>
1127*e4b17023SJohn Marino    struct is_nothrow_copy_assignable
1128*e4b17023SJohn Marino    : public __is_nt_copy_assignable_impl<_Tp>
1129*e4b17023SJohn Marino    { };
1130*e4b17023SJohn Marino
1131*e4b17023SJohn Marino  template<typename _Tp, bool = is_void<_Tp>::value>
1132*e4b17023SJohn Marino    struct __is_nt_move_assignable_impl;
1133*e4b17023SJohn Marino
1134*e4b17023SJohn Marino  template<typename _Tp>
1135*e4b17023SJohn Marino    struct __is_nt_move_assignable_impl<_Tp, true>
1136*e4b17023SJohn Marino    : public false_type { };
1137*e4b17023SJohn Marino
1138*e4b17023SJohn Marino  template<typename _Tp>
1139*e4b17023SJohn Marino    struct __is_nt_move_assignable_impl<_Tp, false>
1140*e4b17023SJohn Marino    : public is_nothrow_assignable<_Tp&, _Tp&&>
1141*e4b17023SJohn Marino    { };
1142*e4b17023SJohn Marino
1143*e4b17023SJohn Marino  /// is_nothrow_move_assignable
1144*e4b17023SJohn Marino  template<typename _Tp>
1145*e4b17023SJohn Marino    struct is_nothrow_move_assignable
1146*e4b17023SJohn Marino    : public __is_nt_move_assignable_impl<_Tp>
1147*e4b17023SJohn Marino    { };
1148*e4b17023SJohn Marino
1149*e4b17023SJohn Marino  /// has_trivial_default_constructor
1150*e4b17023SJohn Marino  template<typename _Tp>
1151*e4b17023SJohn Marino    struct has_trivial_default_constructor
1152*e4b17023SJohn Marino    : public integral_constant<bool, __has_trivial_constructor(_Tp)>
1153*e4b17023SJohn Marino    { };
1154*e4b17023SJohn Marino
1155*e4b17023SJohn Marino  /// has_trivial_copy_constructor
1156*e4b17023SJohn Marino  template<typename _Tp>
1157*e4b17023SJohn Marino    struct has_trivial_copy_constructor
1158*e4b17023SJohn Marino    : public integral_constant<bool, __has_trivial_copy(_Tp)>
1159*e4b17023SJohn Marino    { };
1160*e4b17023SJohn Marino
1161*e4b17023SJohn Marino  /// has_trivial_copy_assign
1162*e4b17023SJohn Marino  template<typename _Tp>
1163*e4b17023SJohn Marino    struct has_trivial_copy_assign
1164*e4b17023SJohn Marino    : public integral_constant<bool, __has_trivial_assign(_Tp)>
1165*e4b17023SJohn Marino    { };
1166*e4b17023SJohn Marino
1167*e4b17023SJohn Marino  /// has_trivial_destructor
1168*e4b17023SJohn Marino  template<typename _Tp>
1169*e4b17023SJohn Marino    struct has_trivial_destructor
1170*e4b17023SJohn Marino    : public integral_constant<bool, __has_trivial_destructor(_Tp)>
1171*e4b17023SJohn Marino    { };
1172*e4b17023SJohn Marino
1173*e4b17023SJohn Marino  /// has_virtual_destructor
1174*e4b17023SJohn Marino  template<typename _Tp>
1175*e4b17023SJohn Marino    struct has_virtual_destructor
1176*e4b17023SJohn Marino    : public integral_constant<bool, __has_virtual_destructor(_Tp)>
1177*e4b17023SJohn Marino    { };
1178*e4b17023SJohn Marino
1179*e4b17023SJohn Marino
1180*e4b17023SJohn Marino  // type property queries.
1181*e4b17023SJohn Marino
1182*e4b17023SJohn Marino  /// alignment_of
1183*e4b17023SJohn Marino  template<typename _Tp>
1184*e4b17023SJohn Marino    struct alignment_of
1185*e4b17023SJohn Marino    : public integral_constant<std::size_t, __alignof__(_Tp)> { };
1186*e4b17023SJohn Marino
1187*e4b17023SJohn Marino  /// rank
1188*e4b17023SJohn Marino  template<typename>
1189*e4b17023SJohn Marino    struct rank
1190*e4b17023SJohn Marino    : public integral_constant<std::size_t, 0> { };
1191*e4b17023SJohn Marino
1192*e4b17023SJohn Marino  template<typename _Tp, std::size_t _Size>
1193*e4b17023SJohn Marino    struct rank<_Tp[_Size]>
1194*e4b17023SJohn Marino    : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
1195*e4b17023SJohn Marino
1196*e4b17023SJohn Marino  template<typename _Tp>
1197*e4b17023SJohn Marino    struct rank<_Tp[]>
1198*e4b17023SJohn Marino    : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
1199*e4b17023SJohn Marino
1200*e4b17023SJohn Marino  /// extent
1201*e4b17023SJohn Marino  template<typename, unsigned _Uint>
1202*e4b17023SJohn Marino    struct extent
1203*e4b17023SJohn Marino    : public integral_constant<std::size_t, 0> { };
1204*e4b17023SJohn Marino
1205*e4b17023SJohn Marino  template<typename _Tp, unsigned _Uint, std::size_t _Size>
1206*e4b17023SJohn Marino    struct extent<_Tp[_Size], _Uint>
1207*e4b17023SJohn Marino    : public integral_constant<std::size_t,
1208*e4b17023SJohn Marino			       _Uint == 0 ? _Size : extent<_Tp,
1209*e4b17023SJohn Marino							   _Uint - 1>::value>
1210*e4b17023SJohn Marino    { };
1211*e4b17023SJohn Marino
1212*e4b17023SJohn Marino  template<typename _Tp, unsigned _Uint>
1213*e4b17023SJohn Marino    struct extent<_Tp[], _Uint>
1214*e4b17023SJohn Marino    : public integral_constant<std::size_t,
1215*e4b17023SJohn Marino			       _Uint == 0 ? 0 : extent<_Tp,
1216*e4b17023SJohn Marino						       _Uint - 1>::value>
1217*e4b17023SJohn Marino    { };
1218*e4b17023SJohn Marino
1219*e4b17023SJohn Marino
1220*e4b17023SJohn Marino  // type relations.
1221*e4b17023SJohn Marino
1222*e4b17023SJohn Marino  /// is_same
1223*e4b17023SJohn Marino  template<typename, typename>
1224*e4b17023SJohn Marino    struct is_same
1225*e4b17023SJohn Marino    : public false_type { };
1226*e4b17023SJohn Marino
1227*e4b17023SJohn Marino  template<typename _Tp>
1228*e4b17023SJohn Marino    struct is_same<_Tp, _Tp>
1229*e4b17023SJohn Marino    : public true_type { };
1230*e4b17023SJohn Marino
1231*e4b17023SJohn Marino  /// is_base_of
1232*e4b17023SJohn Marino  template<typename _Base, typename _Derived>
1233*e4b17023SJohn Marino    struct is_base_of
1234*e4b17023SJohn Marino    : public integral_constant<bool, __is_base_of(_Base, _Derived)>
1235*e4b17023SJohn Marino    { };
1236*e4b17023SJohn Marino
1237*e4b17023SJohn Marino  template<typename _From, typename _To,
1238*e4b17023SJohn Marino           bool = __or_<is_void<_From>, is_function<_To>,
1239*e4b17023SJohn Marino                        is_array<_To>>::value>
1240*e4b17023SJohn Marino    struct __is_convertible_helper
1241*e4b17023SJohn Marino    { static constexpr bool value = is_void<_To>::value; };
1242*e4b17023SJohn Marino
1243*e4b17023SJohn Marino  template<typename _From, typename _To>
1244*e4b17023SJohn Marino    class __is_convertible_helper<_From, _To, false>
1245*e4b17023SJohn Marino    : public __sfinae_types
1246*e4b17023SJohn Marino    {
1247*e4b17023SJohn Marino      template<typename _To1>
1248*e4b17023SJohn Marino        static void __test_aux(_To1);
1249*e4b17023SJohn Marino
1250*e4b17023SJohn Marino      template<typename _From1, typename _To1>
1251*e4b17023SJohn Marino        static decltype(__test_aux<_To1>(std::declval<_From1>()), __one())
1252*e4b17023SJohn Marino	__test(int);
1253*e4b17023SJohn Marino
1254*e4b17023SJohn Marino      template<typename, typename>
1255*e4b17023SJohn Marino        static __two __test(...);
1256*e4b17023SJohn Marino
1257*e4b17023SJohn Marino    public:
1258*e4b17023SJohn Marino      static constexpr bool value = sizeof(__test<_From, _To>(0)) == 1;
1259*e4b17023SJohn Marino    };
1260*e4b17023SJohn Marino
1261*e4b17023SJohn Marino  /// is_convertible
1262*e4b17023SJohn Marino  template<typename _From, typename _To>
1263*e4b17023SJohn Marino    struct is_convertible
1264*e4b17023SJohn Marino    : public integral_constant<bool,
1265*e4b17023SJohn Marino			       __is_convertible_helper<_From, _To>::value>
1266*e4b17023SJohn Marino    { };
1267*e4b17023SJohn Marino
1268*e4b17023SJohn Marino  /// is_explicitly_convertible
1269*e4b17023SJohn Marino  template<typename _From, typename _To>
1270*e4b17023SJohn Marino    struct is_explicitly_convertible
1271*e4b17023SJohn Marino    : public is_constructible<_To, _From>
1272*e4b17023SJohn Marino    { };
1273*e4b17023SJohn Marino
1274*e4b17023SJohn Marino
1275*e4b17023SJohn Marino  // const-volatile modifications.
1276*e4b17023SJohn Marino
1277*e4b17023SJohn Marino  /// remove_const
1278*e4b17023SJohn Marino  template<typename _Tp>
1279*e4b17023SJohn Marino    struct remove_const
1280*e4b17023SJohn Marino    { typedef _Tp     type; };
1281*e4b17023SJohn Marino
1282*e4b17023SJohn Marino  template<typename _Tp>
1283*e4b17023SJohn Marino    struct remove_const<_Tp const>
1284*e4b17023SJohn Marino    { typedef _Tp     type; };
1285*e4b17023SJohn Marino
1286*e4b17023SJohn Marino  /// remove_volatile
1287*e4b17023SJohn Marino  template<typename _Tp>
1288*e4b17023SJohn Marino    struct remove_volatile
1289*e4b17023SJohn Marino    { typedef _Tp     type; };
1290*e4b17023SJohn Marino
1291*e4b17023SJohn Marino  template<typename _Tp>
1292*e4b17023SJohn Marino    struct remove_volatile<_Tp volatile>
1293*e4b17023SJohn Marino    { typedef _Tp     type; };
1294*e4b17023SJohn Marino
1295*e4b17023SJohn Marino  /// remove_cv
1296*e4b17023SJohn Marino  template<typename _Tp>
1297*e4b17023SJohn Marino    struct remove_cv
1298*e4b17023SJohn Marino    {
1299*e4b17023SJohn Marino      typedef typename
1300*e4b17023SJohn Marino      remove_const<typename remove_volatile<_Tp>::type>::type     type;
1301*e4b17023SJohn Marino    };
1302*e4b17023SJohn Marino
1303*e4b17023SJohn Marino  /// add_const
1304*e4b17023SJohn Marino  template<typename _Tp>
1305*e4b17023SJohn Marino    struct add_const
1306*e4b17023SJohn Marino    { typedef _Tp const     type; };
1307*e4b17023SJohn Marino
1308*e4b17023SJohn Marino  /// add_volatile
1309*e4b17023SJohn Marino  template<typename _Tp>
1310*e4b17023SJohn Marino    struct add_volatile
1311*e4b17023SJohn Marino    { typedef _Tp volatile     type; };
1312*e4b17023SJohn Marino
1313*e4b17023SJohn Marino  /// add_cv
1314*e4b17023SJohn Marino  template<typename _Tp>
1315*e4b17023SJohn Marino    struct add_cv
1316*e4b17023SJohn Marino    {
1317*e4b17023SJohn Marino      typedef typename
1318*e4b17023SJohn Marino      add_const<typename add_volatile<_Tp>::type>::type     type;
1319*e4b17023SJohn Marino    };
1320*e4b17023SJohn Marino
1321*e4b17023SJohn Marino
1322*e4b17023SJohn Marino  // Reference transformations.
1323*e4b17023SJohn Marino
1324*e4b17023SJohn Marino  /// remove_reference
1325*e4b17023SJohn Marino  template<typename _Tp>
1326*e4b17023SJohn Marino    struct remove_reference
1327*e4b17023SJohn Marino    { typedef _Tp   type; };
1328*e4b17023SJohn Marino
1329*e4b17023SJohn Marino  template<typename _Tp>
1330*e4b17023SJohn Marino    struct remove_reference<_Tp&>
1331*e4b17023SJohn Marino    { typedef _Tp   type; };
1332*e4b17023SJohn Marino
1333*e4b17023SJohn Marino  template<typename _Tp>
1334*e4b17023SJohn Marino    struct remove_reference<_Tp&&>
1335*e4b17023SJohn Marino    { typedef _Tp   type; };
1336*e4b17023SJohn Marino
1337*e4b17023SJohn Marino  template<typename _Tp,
1338*e4b17023SJohn Marino	   bool = __and_<__not_<is_reference<_Tp>>,
1339*e4b17023SJohn Marino                         __not_<is_void<_Tp>>>::value,
1340*e4b17023SJohn Marino	   bool = is_rvalue_reference<_Tp>::value>
1341*e4b17023SJohn Marino    struct __add_lvalue_reference_helper
1342*e4b17023SJohn Marino    { typedef _Tp   type; };
1343*e4b17023SJohn Marino
1344*e4b17023SJohn Marino  template<typename _Tp>
1345*e4b17023SJohn Marino    struct __add_lvalue_reference_helper<_Tp, true, false>
1346*e4b17023SJohn Marino    { typedef _Tp&   type; };
1347*e4b17023SJohn Marino
1348*e4b17023SJohn Marino  template<typename _Tp>
1349*e4b17023SJohn Marino    struct __add_lvalue_reference_helper<_Tp, false, true>
1350*e4b17023SJohn Marino    { typedef typename remove_reference<_Tp>::type&   type; };
1351*e4b17023SJohn Marino
1352*e4b17023SJohn Marino  /// add_lvalue_reference
1353*e4b17023SJohn Marino  template<typename _Tp>
1354*e4b17023SJohn Marino    struct add_lvalue_reference
1355*e4b17023SJohn Marino    : public __add_lvalue_reference_helper<_Tp>
1356*e4b17023SJohn Marino    { };
1357*e4b17023SJohn Marino
1358*e4b17023SJohn Marino  template<typename _Tp,
1359*e4b17023SJohn Marino           bool = __and_<__not_<is_reference<_Tp>>,
1360*e4b17023SJohn Marino                         __not_<is_void<_Tp>>>::value>
1361*e4b17023SJohn Marino    struct __add_rvalue_reference_helper
1362*e4b17023SJohn Marino    { typedef _Tp   type; };
1363*e4b17023SJohn Marino
1364*e4b17023SJohn Marino  template<typename _Tp>
1365*e4b17023SJohn Marino    struct __add_rvalue_reference_helper<_Tp, true>
1366*e4b17023SJohn Marino    { typedef _Tp&&   type; };
1367*e4b17023SJohn Marino
1368*e4b17023SJohn Marino  /// add_rvalue_reference
1369*e4b17023SJohn Marino  template<typename _Tp>
1370*e4b17023SJohn Marino    struct add_rvalue_reference
1371*e4b17023SJohn Marino    : public __add_rvalue_reference_helper<_Tp>
1372*e4b17023SJohn Marino    { };
1373*e4b17023SJohn Marino
1374*e4b17023SJohn Marino
1375*e4b17023SJohn Marino  // sign modifications.
1376*e4b17023SJohn Marino
1377*e4b17023SJohn Marino  // Utility for constructing identically cv-qualified types.
1378*e4b17023SJohn Marino  template<typename _Unqualified, bool _IsConst, bool _IsVol>
1379*e4b17023SJohn Marino    struct __cv_selector;
1380*e4b17023SJohn Marino
1381*e4b17023SJohn Marino  template<typename _Unqualified>
1382*e4b17023SJohn Marino    struct __cv_selector<_Unqualified, false, false>
1383*e4b17023SJohn Marino    { typedef _Unqualified __type; };
1384*e4b17023SJohn Marino
1385*e4b17023SJohn Marino  template<typename _Unqualified>
1386*e4b17023SJohn Marino    struct __cv_selector<_Unqualified, false, true>
1387*e4b17023SJohn Marino    { typedef volatile _Unqualified __type; };
1388*e4b17023SJohn Marino
1389*e4b17023SJohn Marino  template<typename _Unqualified>
1390*e4b17023SJohn Marino    struct __cv_selector<_Unqualified, true, false>
1391*e4b17023SJohn Marino    { typedef const _Unqualified __type; };
1392*e4b17023SJohn Marino
1393*e4b17023SJohn Marino  template<typename _Unqualified>
1394*e4b17023SJohn Marino    struct __cv_selector<_Unqualified, true, true>
1395*e4b17023SJohn Marino    { typedef const volatile _Unqualified __type; };
1396*e4b17023SJohn Marino
1397*e4b17023SJohn Marino  template<typename _Qualified, typename _Unqualified,
1398*e4b17023SJohn Marino	   bool _IsConst = is_const<_Qualified>::value,
1399*e4b17023SJohn Marino	   bool _IsVol = is_volatile<_Qualified>::value>
1400*e4b17023SJohn Marino    class __match_cv_qualifiers
1401*e4b17023SJohn Marino    {
1402*e4b17023SJohn Marino      typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match;
1403*e4b17023SJohn Marino
1404*e4b17023SJohn Marino    public:
1405*e4b17023SJohn Marino      typedef typename __match::__type __type;
1406*e4b17023SJohn Marino    };
1407*e4b17023SJohn Marino
1408*e4b17023SJohn Marino  // Utility for finding the unsigned versions of signed integral types.
1409*e4b17023SJohn Marino  template<typename _Tp>
1410*e4b17023SJohn Marino    struct __make_unsigned
1411*e4b17023SJohn Marino    { typedef _Tp __type; };
1412*e4b17023SJohn Marino
1413*e4b17023SJohn Marino  template<>
1414*e4b17023SJohn Marino    struct __make_unsigned<char>
1415*e4b17023SJohn Marino    { typedef unsigned char __type; };
1416*e4b17023SJohn Marino
1417*e4b17023SJohn Marino  template<>
1418*e4b17023SJohn Marino    struct __make_unsigned<signed char>
1419*e4b17023SJohn Marino    { typedef unsigned char __type; };
1420*e4b17023SJohn Marino
1421*e4b17023SJohn Marino  template<>
1422*e4b17023SJohn Marino    struct __make_unsigned<short>
1423*e4b17023SJohn Marino    { typedef unsigned short __type; };
1424*e4b17023SJohn Marino
1425*e4b17023SJohn Marino  template<>
1426*e4b17023SJohn Marino    struct __make_unsigned<int>
1427*e4b17023SJohn Marino    { typedef unsigned int __type; };
1428*e4b17023SJohn Marino
1429*e4b17023SJohn Marino  template<>
1430*e4b17023SJohn Marino    struct __make_unsigned<long>
1431*e4b17023SJohn Marino    { typedef unsigned long __type; };
1432*e4b17023SJohn Marino
1433*e4b17023SJohn Marino  template<>
1434*e4b17023SJohn Marino    struct __make_unsigned<long long>
1435*e4b17023SJohn Marino    { typedef unsigned long long __type; };
1436*e4b17023SJohn Marino
1437*e4b17023SJohn Marino#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
1438*e4b17023SJohn Marino  template<>
1439*e4b17023SJohn Marino    struct __make_unsigned<__int128>
1440*e4b17023SJohn Marino    { typedef unsigned __int128 __type; };
1441*e4b17023SJohn Marino#endif
1442*e4b17023SJohn Marino
1443*e4b17023SJohn Marino  // Select between integral and enum: not possible to be both.
1444*e4b17023SJohn Marino  template<typename _Tp,
1445*e4b17023SJohn Marino	   bool _IsInt = is_integral<_Tp>::value,
1446*e4b17023SJohn Marino	   bool _IsEnum = is_enum<_Tp>::value>
1447*e4b17023SJohn Marino    class __make_unsigned_selector;
1448*e4b17023SJohn Marino
1449*e4b17023SJohn Marino  template<typename _Tp>
1450*e4b17023SJohn Marino    class __make_unsigned_selector<_Tp, true, false>
1451*e4b17023SJohn Marino    {
1452*e4b17023SJohn Marino      typedef __make_unsigned<typename remove_cv<_Tp>::type> __unsignedt;
1453*e4b17023SJohn Marino      typedef typename __unsignedt::__type __unsigned_type;
1454*e4b17023SJohn Marino      typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned;
1455*e4b17023SJohn Marino
1456*e4b17023SJohn Marino    public:
1457*e4b17023SJohn Marino      typedef typename __cv_unsigned::__type __type;
1458*e4b17023SJohn Marino    };
1459*e4b17023SJohn Marino
1460*e4b17023SJohn Marino  template<typename _Tp>
1461*e4b17023SJohn Marino    class __make_unsigned_selector<_Tp, false, true>
1462*e4b17023SJohn Marino    {
1463*e4b17023SJohn Marino      // With -fshort-enums, an enum may be as small as a char.
1464*e4b17023SJohn Marino      typedef unsigned char __smallest;
1465*e4b17023SJohn Marino      static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
1466*e4b17023SJohn Marino      static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned short);
1467*e4b17023SJohn Marino      static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int);
1468*e4b17023SJohn Marino      typedef conditional<__b2, unsigned int, unsigned long> __cond2;
1469*e4b17023SJohn Marino      typedef typename __cond2::type __cond2_type;
1470*e4b17023SJohn Marino      typedef conditional<__b1, unsigned short, __cond2_type> __cond1;
1471*e4b17023SJohn Marino      typedef typename __cond1::type __cond1_type;
1472*e4b17023SJohn Marino
1473*e4b17023SJohn Marino    public:
1474*e4b17023SJohn Marino      typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
1475*e4b17023SJohn Marino    };
1476*e4b17023SJohn Marino
1477*e4b17023SJohn Marino  // Given an integral/enum type, return the corresponding unsigned
1478*e4b17023SJohn Marino  // integer type.
1479*e4b17023SJohn Marino  // Primary template.
1480*e4b17023SJohn Marino  /// make_unsigned
1481*e4b17023SJohn Marino  template<typename _Tp>
1482*e4b17023SJohn Marino    struct make_unsigned
1483*e4b17023SJohn Marino    { typedef typename __make_unsigned_selector<_Tp>::__type type; };
1484*e4b17023SJohn Marino
1485*e4b17023SJohn Marino  // Integral, but don't define.
1486*e4b17023SJohn Marino  template<>
1487*e4b17023SJohn Marino    struct make_unsigned<bool>;
1488*e4b17023SJohn Marino
1489*e4b17023SJohn Marino
1490*e4b17023SJohn Marino  // Utility for finding the signed versions of unsigned integral types.
1491*e4b17023SJohn Marino  template<typename _Tp>
1492*e4b17023SJohn Marino    struct __make_signed
1493*e4b17023SJohn Marino    { typedef _Tp __type; };
1494*e4b17023SJohn Marino
1495*e4b17023SJohn Marino  template<>
1496*e4b17023SJohn Marino    struct __make_signed<char>
1497*e4b17023SJohn Marino    { typedef signed char __type; };
1498*e4b17023SJohn Marino
1499*e4b17023SJohn Marino  template<>
1500*e4b17023SJohn Marino    struct __make_signed<unsigned char>
1501*e4b17023SJohn Marino    { typedef signed char __type; };
1502*e4b17023SJohn Marino
1503*e4b17023SJohn Marino  template<>
1504*e4b17023SJohn Marino    struct __make_signed<unsigned short>
1505*e4b17023SJohn Marino    { typedef signed short __type; };
1506*e4b17023SJohn Marino
1507*e4b17023SJohn Marino  template<>
1508*e4b17023SJohn Marino    struct __make_signed<unsigned int>
1509*e4b17023SJohn Marino    { typedef signed int __type; };
1510*e4b17023SJohn Marino
1511*e4b17023SJohn Marino  template<>
1512*e4b17023SJohn Marino    struct __make_signed<unsigned long>
1513*e4b17023SJohn Marino    { typedef signed long __type; };
1514*e4b17023SJohn Marino
1515*e4b17023SJohn Marino  template<>
1516*e4b17023SJohn Marino    struct __make_signed<unsigned long long>
1517*e4b17023SJohn Marino    { typedef signed long long __type; };
1518*e4b17023SJohn Marino
1519*e4b17023SJohn Marino#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
1520*e4b17023SJohn Marino  template<>
1521*e4b17023SJohn Marino    struct __make_signed<unsigned __int128>
1522*e4b17023SJohn Marino    { typedef __int128 __type; };
1523*e4b17023SJohn Marino#endif
1524*e4b17023SJohn Marino
1525*e4b17023SJohn Marino  // Select between integral and enum: not possible to be both.
1526*e4b17023SJohn Marino  template<typename _Tp,
1527*e4b17023SJohn Marino	   bool _IsInt = is_integral<_Tp>::value,
1528*e4b17023SJohn Marino	   bool _IsEnum = is_enum<_Tp>::value>
1529*e4b17023SJohn Marino    class __make_signed_selector;
1530*e4b17023SJohn Marino
1531*e4b17023SJohn Marino  template<typename _Tp>
1532*e4b17023SJohn Marino    class __make_signed_selector<_Tp, true, false>
1533*e4b17023SJohn Marino    {
1534*e4b17023SJohn Marino      typedef __make_signed<typename remove_cv<_Tp>::type> __signedt;
1535*e4b17023SJohn Marino      typedef typename __signedt::__type __signed_type;
1536*e4b17023SJohn Marino      typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed;
1537*e4b17023SJohn Marino
1538*e4b17023SJohn Marino    public:
1539*e4b17023SJohn Marino      typedef typename __cv_signed::__type __type;
1540*e4b17023SJohn Marino    };
1541*e4b17023SJohn Marino
1542*e4b17023SJohn Marino  template<typename _Tp>
1543*e4b17023SJohn Marino    class __make_signed_selector<_Tp, false, true>
1544*e4b17023SJohn Marino    {
1545*e4b17023SJohn Marino      // With -fshort-enums, an enum may be as small as a char.
1546*e4b17023SJohn Marino      typedef signed char __smallest;
1547*e4b17023SJohn Marino      static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
1548*e4b17023SJohn Marino      static const bool __b1 = sizeof(_Tp) <= sizeof(signed short);
1549*e4b17023SJohn Marino      static const bool __b2 = sizeof(_Tp) <= sizeof(signed int);
1550*e4b17023SJohn Marino      typedef conditional<__b2, signed int, signed long> __cond2;
1551*e4b17023SJohn Marino      typedef typename __cond2::type __cond2_type;
1552*e4b17023SJohn Marino      typedef conditional<__b1, signed short, __cond2_type> __cond1;
1553*e4b17023SJohn Marino      typedef typename __cond1::type __cond1_type;
1554*e4b17023SJohn Marino
1555*e4b17023SJohn Marino    public:
1556*e4b17023SJohn Marino      typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
1557*e4b17023SJohn Marino    };
1558*e4b17023SJohn Marino
1559*e4b17023SJohn Marino  // Given an integral/enum type, return the corresponding signed
1560*e4b17023SJohn Marino  // integer type.
1561*e4b17023SJohn Marino  // Primary template.
1562*e4b17023SJohn Marino  /// make_signed
1563*e4b17023SJohn Marino  template<typename _Tp>
1564*e4b17023SJohn Marino    struct make_signed
1565*e4b17023SJohn Marino    { typedef typename __make_signed_selector<_Tp>::__type type; };
1566*e4b17023SJohn Marino
1567*e4b17023SJohn Marino  // Integral, but don't define.
1568*e4b17023SJohn Marino  template<>
1569*e4b17023SJohn Marino    struct make_signed<bool>;
1570*e4b17023SJohn Marino
1571*e4b17023SJohn Marino
1572*e4b17023SJohn Marino  // array modifications.
1573*e4b17023SJohn Marino
1574*e4b17023SJohn Marino  /// remove_extent
1575*e4b17023SJohn Marino  template<typename _Tp>
1576*e4b17023SJohn Marino    struct remove_extent
1577*e4b17023SJohn Marino    { typedef _Tp     type; };
1578*e4b17023SJohn Marino
1579*e4b17023SJohn Marino  template<typename _Tp, std::size_t _Size>
1580*e4b17023SJohn Marino    struct remove_extent<_Tp[_Size]>
1581*e4b17023SJohn Marino    { typedef _Tp     type; };
1582*e4b17023SJohn Marino
1583*e4b17023SJohn Marino  template<typename _Tp>
1584*e4b17023SJohn Marino    struct remove_extent<_Tp[]>
1585*e4b17023SJohn Marino    { typedef _Tp     type; };
1586*e4b17023SJohn Marino
1587*e4b17023SJohn Marino  /// remove_all_extents
1588*e4b17023SJohn Marino  template<typename _Tp>
1589*e4b17023SJohn Marino    struct remove_all_extents
1590*e4b17023SJohn Marino    { typedef _Tp     type; };
1591*e4b17023SJohn Marino
1592*e4b17023SJohn Marino  template<typename _Tp, std::size_t _Size>
1593*e4b17023SJohn Marino    struct remove_all_extents<_Tp[_Size]>
1594*e4b17023SJohn Marino    { typedef typename remove_all_extents<_Tp>::type     type; };
1595*e4b17023SJohn Marino
1596*e4b17023SJohn Marino  template<typename _Tp>
1597*e4b17023SJohn Marino    struct remove_all_extents<_Tp[]>
1598*e4b17023SJohn Marino    { typedef typename remove_all_extents<_Tp>::type     type; };
1599*e4b17023SJohn Marino
1600*e4b17023SJohn Marino
1601*e4b17023SJohn Marino  // pointer modifications.
1602*e4b17023SJohn Marino
1603*e4b17023SJohn Marino  template<typename _Tp, typename>
1604*e4b17023SJohn Marino    struct __remove_pointer_helper
1605*e4b17023SJohn Marino    { typedef _Tp     type; };
1606*e4b17023SJohn Marino
1607*e4b17023SJohn Marino  template<typename _Tp, typename _Up>
1608*e4b17023SJohn Marino    struct __remove_pointer_helper<_Tp, _Up*>
1609*e4b17023SJohn Marino    { typedef _Up     type; };
1610*e4b17023SJohn Marino
1611*e4b17023SJohn Marino  /// remove_pointer
1612*e4b17023SJohn Marino  template<typename _Tp>
1613*e4b17023SJohn Marino    struct remove_pointer
1614*e4b17023SJohn Marino    : public __remove_pointer_helper<_Tp, typename remove_cv<_Tp>::type>
1615*e4b17023SJohn Marino    { };
1616*e4b17023SJohn Marino
1617*e4b17023SJohn Marino  /// add_pointer
1618*e4b17023SJohn Marino  template<typename _Tp>
1619*e4b17023SJohn Marino    struct add_pointer
1620*e4b17023SJohn Marino    { typedef typename remove_reference<_Tp>::type*     type; };
1621*e4b17023SJohn Marino
1622*e4b17023SJohn Marino
1623*e4b17023SJohn Marino  template<std::size_t _Len>
1624*e4b17023SJohn Marino    struct __aligned_storage_msa
1625*e4b17023SJohn Marino    {
1626*e4b17023SJohn Marino      union __type
1627*e4b17023SJohn Marino      {
1628*e4b17023SJohn Marino	unsigned char __data[_Len];
1629*e4b17023SJohn Marino	struct __attribute__((__aligned__)) { } __align;
1630*e4b17023SJohn Marino      };
1631*e4b17023SJohn Marino    };
1632*e4b17023SJohn Marino
1633*e4b17023SJohn Marino  /**
1634*e4b17023SJohn Marino   *  @brief Alignment type.
1635*e4b17023SJohn Marino   *
1636*e4b17023SJohn Marino   *  The value of _Align is a default-alignment which shall be the
1637*e4b17023SJohn Marino   *  most stringent alignment requirement for any C++ object type
1638*e4b17023SJohn Marino   *  whose size is no greater than _Len (3.9). The member typedef
1639*e4b17023SJohn Marino   *  type shall be a POD type suitable for use as uninitialized
1640*e4b17023SJohn Marino   *  storage for any object whose size is at most _Len and whose
1641*e4b17023SJohn Marino   *  alignment is a divisor of _Align.
1642*e4b17023SJohn Marino  */
1643*e4b17023SJohn Marino  template<std::size_t _Len, std::size_t _Align =
1644*e4b17023SJohn Marino	   __alignof__(typename __aligned_storage_msa<_Len>::__type)>
1645*e4b17023SJohn Marino    struct aligned_storage
1646*e4b17023SJohn Marino    {
1647*e4b17023SJohn Marino      union type
1648*e4b17023SJohn Marino      {
1649*e4b17023SJohn Marino	unsigned char __data[_Len];
1650*e4b17023SJohn Marino	struct __attribute__((__aligned__((_Align)))) { } __align;
1651*e4b17023SJohn Marino      };
1652*e4b17023SJohn Marino    };
1653*e4b17023SJohn Marino
1654*e4b17023SJohn Marino
1655*e4b17023SJohn Marino  // Decay trait for arrays and functions, used for perfect forwarding
1656*e4b17023SJohn Marino  // in make_pair, make_tuple, etc.
1657*e4b17023SJohn Marino  template<typename _Up,
1658*e4b17023SJohn Marino	   bool _IsArray = is_array<_Up>::value,
1659*e4b17023SJohn Marino	   bool _IsFunction = is_function<_Up>::value>
1660*e4b17023SJohn Marino    struct __decay_selector;
1661*e4b17023SJohn Marino
1662*e4b17023SJohn Marino  // NB: DR 705.
1663*e4b17023SJohn Marino  template<typename _Up>
1664*e4b17023SJohn Marino    struct __decay_selector<_Up, false, false>
1665*e4b17023SJohn Marino    { typedef typename remove_cv<_Up>::type __type; };
1666*e4b17023SJohn Marino
1667*e4b17023SJohn Marino  template<typename _Up>
1668*e4b17023SJohn Marino    struct __decay_selector<_Up, true, false>
1669*e4b17023SJohn Marino    { typedef typename remove_extent<_Up>::type* __type; };
1670*e4b17023SJohn Marino
1671*e4b17023SJohn Marino  template<typename _Up>
1672*e4b17023SJohn Marino    struct __decay_selector<_Up, false, true>
1673*e4b17023SJohn Marino    { typedef typename add_pointer<_Up>::type __type; };
1674*e4b17023SJohn Marino
1675*e4b17023SJohn Marino  /// decay
1676*e4b17023SJohn Marino  template<typename _Tp>
1677*e4b17023SJohn Marino    class decay
1678*e4b17023SJohn Marino    {
1679*e4b17023SJohn Marino      typedef typename remove_reference<_Tp>::type __remove_type;
1680*e4b17023SJohn Marino
1681*e4b17023SJohn Marino    public:
1682*e4b17023SJohn Marino      typedef typename __decay_selector<__remove_type>::__type type;
1683*e4b17023SJohn Marino    };
1684*e4b17023SJohn Marino
1685*e4b17023SJohn Marino  template<typename _Tp>
1686*e4b17023SJohn Marino    class reference_wrapper;
1687*e4b17023SJohn Marino
1688*e4b17023SJohn Marino  // Helper which adds a reference to a type when given a reference_wrapper
1689*e4b17023SJohn Marino  template<typename _Tp>
1690*e4b17023SJohn Marino    struct __strip_reference_wrapper
1691*e4b17023SJohn Marino    {
1692*e4b17023SJohn Marino      typedef _Tp __type;
1693*e4b17023SJohn Marino    };
1694*e4b17023SJohn Marino
1695*e4b17023SJohn Marino  template<typename _Tp>
1696*e4b17023SJohn Marino    struct __strip_reference_wrapper<reference_wrapper<_Tp> >
1697*e4b17023SJohn Marino    {
1698*e4b17023SJohn Marino      typedef _Tp& __type;
1699*e4b17023SJohn Marino    };
1700*e4b17023SJohn Marino
1701*e4b17023SJohn Marino  template<typename _Tp>
1702*e4b17023SJohn Marino    struct __strip_reference_wrapper<const reference_wrapper<_Tp> >
1703*e4b17023SJohn Marino    {
1704*e4b17023SJohn Marino      typedef _Tp& __type;
1705*e4b17023SJohn Marino    };
1706*e4b17023SJohn Marino
1707*e4b17023SJohn Marino  template<typename _Tp>
1708*e4b17023SJohn Marino    struct __decay_and_strip
1709*e4b17023SJohn Marino    {
1710*e4b17023SJohn Marino      typedef typename __strip_reference_wrapper<
1711*e4b17023SJohn Marino	typename decay<_Tp>::type>::__type __type;
1712*e4b17023SJohn Marino    };
1713*e4b17023SJohn Marino
1714*e4b17023SJohn Marino
1715*e4b17023SJohn Marino  // Primary template.
1716*e4b17023SJohn Marino  /// Define a member typedef @c type only if a boolean constant is true.
1717*e4b17023SJohn Marino  template<bool, typename _Tp = void>
1718*e4b17023SJohn Marino    struct enable_if
1719*e4b17023SJohn Marino    { };
1720*e4b17023SJohn Marino
1721*e4b17023SJohn Marino  // Partial specialization for true.
1722*e4b17023SJohn Marino  template<typename _Tp>
1723*e4b17023SJohn Marino    struct enable_if<true, _Tp>
1724*e4b17023SJohn Marino    { typedef _Tp type; };
1725*e4b17023SJohn Marino
1726*e4b17023SJohn Marino
1727*e4b17023SJohn Marino  // Primary template.
1728*e4b17023SJohn Marino  /// Define a member typedef @c type to one of two argument types.
1729*e4b17023SJohn Marino  template<bool _Cond, typename _Iftrue, typename _Iffalse>
1730*e4b17023SJohn Marino    struct conditional
1731*e4b17023SJohn Marino    { typedef _Iftrue type; };
1732*e4b17023SJohn Marino
1733*e4b17023SJohn Marino  // Partial specialization for false.
1734*e4b17023SJohn Marino  template<typename _Iftrue, typename _Iffalse>
1735*e4b17023SJohn Marino    struct conditional<false, _Iftrue, _Iffalse>
1736*e4b17023SJohn Marino    { typedef _Iffalse type; };
1737*e4b17023SJohn Marino
1738*e4b17023SJohn Marino
1739*e4b17023SJohn Marino  /// common_type
1740*e4b17023SJohn Marino  template<typename... _Tp>
1741*e4b17023SJohn Marino    struct common_type;
1742*e4b17023SJohn Marino
1743*e4b17023SJohn Marino  template<typename _Tp>
1744*e4b17023SJohn Marino    struct common_type<_Tp>
1745*e4b17023SJohn Marino    { typedef _Tp type; };
1746*e4b17023SJohn Marino
1747*e4b17023SJohn Marino  template<typename _Tp, typename _Up>
1748*e4b17023SJohn Marino    struct common_type<_Tp, _Up>
1749*e4b17023SJohn Marino    { typedef decltype(true ? declval<_Tp>() : declval<_Up>()) type; };
1750*e4b17023SJohn Marino
1751*e4b17023SJohn Marino  template<typename _Tp, typename _Up, typename... _Vp>
1752*e4b17023SJohn Marino    struct common_type<_Tp, _Up, _Vp...>
1753*e4b17023SJohn Marino    {
1754*e4b17023SJohn Marino      typedef typename
1755*e4b17023SJohn Marino        common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type;
1756*e4b17023SJohn Marino    };
1757*e4b17023SJohn Marino
1758*e4b17023SJohn Marino  /// The underlying type of an enum.
1759*e4b17023SJohn Marino  template<typename _Tp>
1760*e4b17023SJohn Marino    struct underlying_type
1761*e4b17023SJohn Marino    {
1762*e4b17023SJohn Marino      typedef __underlying_type(_Tp) type;
1763*e4b17023SJohn Marino    };
1764*e4b17023SJohn Marino
1765*e4b17023SJohn Marino  template<typename _Tp>
1766*e4b17023SJohn Marino    struct __declval_protector
1767*e4b17023SJohn Marino    {
1768*e4b17023SJohn Marino      static const bool __stop = false;
1769*e4b17023SJohn Marino      static typename add_rvalue_reference<_Tp>::type __delegate();
1770*e4b17023SJohn Marino    };
1771*e4b17023SJohn Marino
1772*e4b17023SJohn Marino  template<typename _Tp>
1773*e4b17023SJohn Marino    inline typename add_rvalue_reference<_Tp>::type
1774*e4b17023SJohn Marino    declval() noexcept
1775*e4b17023SJohn Marino    {
1776*e4b17023SJohn Marino      static_assert(__declval_protector<_Tp>::__stop,
1777*e4b17023SJohn Marino		    "declval() must not be used!");
1778*e4b17023SJohn Marino      return __declval_protector<_Tp>::__delegate();
1779*e4b17023SJohn Marino    }
1780*e4b17023SJohn Marino
1781*e4b17023SJohn Marino  /// result_of
1782*e4b17023SJohn Marino  template<typename _Signature>
1783*e4b17023SJohn Marino    class result_of;
1784*e4b17023SJohn Marino
1785*e4b17023SJohn Marino  template<typename _MemPtr, typename _Arg>
1786*e4b17023SJohn Marino    struct _Result_of_memobj;
1787*e4b17023SJohn Marino
1788*e4b17023SJohn Marino  template<typename _Res, typename _Class, typename _Arg>
1789*e4b17023SJohn Marino    struct _Result_of_memobj<_Res _Class::*, _Arg>
1790*e4b17023SJohn Marino    {
1791*e4b17023SJohn Marino    private:
1792*e4b17023SJohn Marino      typedef _Res _Class::* _Func;
1793*e4b17023SJohn Marino
1794*e4b17023SJohn Marino      template<typename _Tp>
1795*e4b17023SJohn Marino	static _Tp _S_get(const _Class&);
1796*e4b17023SJohn Marino      template<typename _Tp>
1797*e4b17023SJohn Marino	static decltype(*std::declval<_Tp>()) _S_get(...);
1798*e4b17023SJohn Marino
1799*e4b17023SJohn Marino    public:
1800*e4b17023SJohn Marino      typedef
1801*e4b17023SJohn Marino        decltype(_S_get<_Arg>(std::declval<_Arg>()).*std::declval<_Func>())
1802*e4b17023SJohn Marino        __type;
1803*e4b17023SJohn Marino    };
1804*e4b17023SJohn Marino
1805*e4b17023SJohn Marino  template<typename _MemPtr, typename _Arg, typename... _ArgTypes>
1806*e4b17023SJohn Marino    struct _Result_of_memfun;
1807*e4b17023SJohn Marino
1808*e4b17023SJohn Marino  template<typename _Res, typename _Class, typename _Arg, typename... _Args>
1809*e4b17023SJohn Marino    struct _Result_of_memfun<_Res _Class::*, _Arg, _Args...>
1810*e4b17023SJohn Marino    {
1811*e4b17023SJohn Marino    private:
1812*e4b17023SJohn Marino      typedef _Res _Class::* _Func;
1813*e4b17023SJohn Marino
1814*e4b17023SJohn Marino      template<typename _Tp>
1815*e4b17023SJohn Marino	static _Tp _S_get(const _Class&);
1816*e4b17023SJohn Marino      template<typename _Tp>
1817*e4b17023SJohn Marino	static decltype(*std::declval<_Tp>()) _S_get(...);
1818*e4b17023SJohn Marino
1819*e4b17023SJohn Marino    public:
1820*e4b17023SJohn Marino      typedef
1821*e4b17023SJohn Marino        decltype((_S_get<_Arg>(std::declval<_Arg>()).*std::declval<_Func>())
1822*e4b17023SJohn Marino            (std::declval<_Args>()...) )
1823*e4b17023SJohn Marino        __type;
1824*e4b17023SJohn Marino    };
1825*e4b17023SJohn Marino
1826*e4b17023SJohn Marino  template<bool, bool, typename _Functor, typename... _ArgTypes>
1827*e4b17023SJohn Marino    struct _Result_of_impl;
1828*e4b17023SJohn Marino
1829*e4b17023SJohn Marino  template<typename _Functor, typename... _ArgTypes>
1830*e4b17023SJohn Marino    struct _Result_of_impl<false, false, _Functor, _ArgTypes...>
1831*e4b17023SJohn Marino    {
1832*e4b17023SJohn Marino      typedef
1833*e4b17023SJohn Marino        decltype( std::declval<_Functor>()(std::declval<_ArgTypes>()...) )
1834*e4b17023SJohn Marino        __type;
1835*e4b17023SJohn Marino    };
1836*e4b17023SJohn Marino
1837*e4b17023SJohn Marino  template<typename _MemPtr, typename _Arg>
1838*e4b17023SJohn Marino    struct _Result_of_impl<true, false, _MemPtr, _Arg>
1839*e4b17023SJohn Marino    : _Result_of_memobj<typename remove_reference<_MemPtr>::type, _Arg>
1840*e4b17023SJohn Marino    {
1841*e4b17023SJohn Marino      typedef typename _Result_of_memobj<
1842*e4b17023SJohn Marino	typename remove_reference<_MemPtr>::type, _Arg>::__type
1843*e4b17023SJohn Marino	__type;
1844*e4b17023SJohn Marino    };
1845*e4b17023SJohn Marino
1846*e4b17023SJohn Marino  template<typename _MemPtr, typename _Arg, typename... _ArgTypes>
1847*e4b17023SJohn Marino    struct _Result_of_impl<false, true, _MemPtr, _Arg, _ArgTypes...>
1848*e4b17023SJohn Marino    : _Result_of_memfun<typename remove_reference<_MemPtr>::type, _Arg,
1849*e4b17023SJohn Marino                        _ArgTypes...>
1850*e4b17023SJohn Marino    {
1851*e4b17023SJohn Marino      typedef typename _Result_of_memfun<
1852*e4b17023SJohn Marino	typename remove_reference<_MemPtr>::type, _Arg, _ArgTypes...>::__type
1853*e4b17023SJohn Marino	__type;
1854*e4b17023SJohn Marino    };
1855*e4b17023SJohn Marino
1856*e4b17023SJohn Marino  template<typename _Functor, typename... _ArgTypes>
1857*e4b17023SJohn Marino    struct result_of<_Functor(_ArgTypes...)>
1858*e4b17023SJohn Marino    : _Result_of_impl<is_member_object_pointer<
1859*e4b17023SJohn Marino                        typename remove_reference<_Functor>::type >::value,
1860*e4b17023SJohn Marino                      is_member_function_pointer<
1861*e4b17023SJohn Marino			typename remove_reference<_Functor>::type >::value,
1862*e4b17023SJohn Marino		      _Functor, _ArgTypes...>
1863*e4b17023SJohn Marino    {
1864*e4b17023SJohn Marino      typedef typename _Result_of_impl<
1865*e4b17023SJohn Marino	is_member_object_pointer<
1866*e4b17023SJohn Marino	  typename remove_reference<_Functor>::type >::value,
1867*e4b17023SJohn Marino        is_member_function_pointer<
1868*e4b17023SJohn Marino	  typename remove_reference<_Functor>::type >::value,
1869*e4b17023SJohn Marino       	_Functor, _ArgTypes...>::__type
1870*e4b17023SJohn Marino	type;
1871*e4b17023SJohn Marino    };
1872*e4b17023SJohn Marino
1873*e4b17023SJohn Marino  /**
1874*e4b17023SJohn Marino   *  Use SFINAE to determine if the type _Tp has a publicly-accessible
1875*e4b17023SJohn Marino   *  member type _NTYPE.
1876*e4b17023SJohn Marino   */
1877*e4b17023SJohn Marino#define _GLIBCXX_HAS_NESTED_TYPE(_NTYPE)                         \
1878*e4b17023SJohn Marino  template<typename _Tp>                                         \
1879*e4b17023SJohn Marino    class __has_##_NTYPE##_helper                                \
1880*e4b17023SJohn Marino    : __sfinae_types                                             \
1881*e4b17023SJohn Marino    {                                                            \
1882*e4b17023SJohn Marino      template<typename _Up>                                     \
1883*e4b17023SJohn Marino        struct _Wrap_type                                        \
1884*e4b17023SJohn Marino	{ };                                                     \
1885*e4b17023SJohn Marino                                                                 \
1886*e4b17023SJohn Marino      template<typename _Up>                                     \
1887*e4b17023SJohn Marino        static __one __test(_Wrap_type<typename _Up::_NTYPE>*);  \
1888*e4b17023SJohn Marino                                                                 \
1889*e4b17023SJohn Marino      template<typename _Up>                                     \
1890*e4b17023SJohn Marino        static __two __test(...);                                \
1891*e4b17023SJohn Marino                                                                 \
1892*e4b17023SJohn Marino    public:                                                      \
1893*e4b17023SJohn Marino      static constexpr bool value = sizeof(__test<_Tp>(0)) == 1; \
1894*e4b17023SJohn Marino    };                                                           \
1895*e4b17023SJohn Marino                                                                 \
1896*e4b17023SJohn Marino  template<typename _Tp>                                         \
1897*e4b17023SJohn Marino    struct __has_##_NTYPE                                        \
1898*e4b17023SJohn Marino    : integral_constant<bool, __has_##_NTYPE##_helper            \
1899*e4b17023SJohn Marino			<typename remove_cv<_Tp>::type>::value>  \
1900*e4b17023SJohn Marino    { };
1901*e4b17023SJohn Marino
1902*e4b17023SJohn Marino  /// @} group metaprogramming
1903*e4b17023SJohn Marino_GLIBCXX_END_NAMESPACE_VERSION
1904*e4b17023SJohn Marino} // namespace
1905*e4b17023SJohn Marino
1906*e4b17023SJohn Marino#endif  // __GXX_EXPERIMENTAL_CXX0X__
1907*e4b17023SJohn Marino
1908*e4b17023SJohn Marino#endif  // _GLIBCXX_TYPE_TRAITS
1909