1169691Skan// TR1 type_traits -*- C++ -*-
2169691Skan
3169691Skan// Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
4169691Skan//
5169691Skan// This file is part of the GNU ISO C++ Library.  This library is free
6169691Skan// software; you can redistribute it and/or modify it under the
7169691Skan// terms of the GNU General Public License as published by the
8169691Skan// Free Software Foundation; either version 2, or (at your option)
9169691Skan// any later version.
10169691Skan
11169691Skan// This library is distributed in the hope that it will be useful,
12169691Skan// but WITHOUT ANY WARRANTY; without even the implied warranty of
13169691Skan// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14169691Skan// GNU General Public License for more details.
15169691Skan
16169691Skan// You should have received a copy of the GNU General Public License along
17169691Skan// with this library; see the file COPYING.  If not, write to the Free
18169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19169691Skan// USA.
20169691Skan
21169691Skan// As a special exception, you may use this file as part of a free software
22169691Skan// library without restriction.  Specifically, if other files instantiate
23169691Skan// templates or use macros or inline functions from this file, or you compile
24169691Skan// this file and link it with other files to produce an executable, this
25169691Skan// file does not by itself cause the resulting executable to be covered by
26169691Skan// the GNU General Public License.  This exception does not however
27169691Skan// invalidate any other reasons why the executable file might be covered by
28169691Skan// the GNU General Public License.
29169691Skan
30169691Skan/** @file tr1/type_traits
31169691Skan *  This is a TR1 C++ Library header. 
32169691Skan */
33169691Skan
34169691Skan#ifndef _TR1_TYPE_TRAITS
35169691Skan#define _TR1_TYPE_TRAITS 1
36169691Skan
37169691Skan#include <bits/c++config.h>
38169691Skan#include <tr1/type_traits_fwd.h>
39169691Skan
40169691Skan// namespace std::tr1
41169691Skannamespace std
42169691Skan{
43169691Skan_GLIBCXX_BEGIN_NAMESPACE(tr1)
44169691Skan
45169691Skan  // For use in __in_array and elsewhere.
46169691Skan  struct __sfinae_types
47169691Skan  {
48169691Skan    typedef char __one;
49169691Skan    typedef struct { char __arr[2]; } __two;
50169691Skan  };
51169691Skan
52169691Skan  template<typename _Tp>
53169691Skan    struct __in_array
54169691Skan    : public __sfinae_types
55169691Skan    {
56169691Skan    private:
57169691Skan      template<typename _Up>
58169691Skan        static __one __test(_Up(*)[1]);
59169691Skan      template<typename>
60169691Skan        static __two __test(...);
61169691Skan    
62169691Skan    public:
63169691Skan      static const bool __value = sizeof(__test<_Tp>(0)) == 1;
64169691Skan    };
65169691Skan
66169691Skan#define _DEFINE_SPEC_BODY(_Value)                                    \
67169691Skan    : public integral_constant<bool, _Value> { };
68169691Skan
69169691Skan#define _DEFINE_SPEC_0_HELPER(_Spec, _Value)                         \
70169691Skan  template<>                                                         \
71169691Skan    struct _Spec                                                     \
72169691Skan    _DEFINE_SPEC_BODY(_Value)
73169691Skan
74169691Skan#define _DEFINE_SPEC_1_HELPER(_Spec, _Value)                         \
75169691Skan  template<typename _Tp>                                             \
76169691Skan    struct _Spec                                                     \
77169691Skan    _DEFINE_SPEC_BODY(_Value)
78169691Skan      
79169691Skan#define _DEFINE_SPEC_2_HELPER(_Spec, _Value)                         \
80169691Skan  template<typename _Tp, typename _Cp>                               \
81169691Skan    struct _Spec                                                     \
82169691Skan    _DEFINE_SPEC_BODY(_Value)
83169691Skan
84169691Skan#define _DEFINE_SPEC(_Order, _Trait, _Type, _Value)                  \
85169691Skan  _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type>, _Value)              \
86169691Skan  _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type const>, _Value)        \
87169691Skan  _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type volatile>, _Value)     \
88169691Skan  _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type const volatile>, _Value)
89169691Skan
90169691Skan  /// @brief  helper classes [4.3].
91169691Skan  template<typename _Tp, _Tp __v>
92169691Skan    struct integral_constant
93169691Skan    {
94169691Skan      static const _Tp                      value = __v;
95169691Skan      typedef _Tp                           value_type;
96169691Skan      typedef integral_constant<_Tp, __v>   type;
97169691Skan    };
98169691Skan  typedef integral_constant<bool, true>     true_type;
99169691Skan  typedef integral_constant<bool, false>    false_type;
100169691Skan
101169691Skan  template<typename _Tp, _Tp __v>
102169691Skan    const _Tp integral_constant<_Tp, __v>::value;
103169691Skan
104169691Skan  /// @brief  primary type categories [4.5.1].
105169691Skan  template<typename>
106169691Skan    struct is_void
107169691Skan    : public false_type { };
108169691Skan  _DEFINE_SPEC(0, is_void, void, true)
109169691Skan
110169691Skan  template<typename>
111169691Skan    struct is_integral
112169691Skan    : public false_type { };
113169691Skan  _DEFINE_SPEC(0, is_integral, bool, true)
114169691Skan  _DEFINE_SPEC(0, is_integral, char, true)
115169691Skan  _DEFINE_SPEC(0, is_integral, signed char, true)
116169691Skan  _DEFINE_SPEC(0, is_integral, unsigned char, true)
117169691Skan#ifdef _GLIBCXX_USE_WCHAR_T
118169691Skan  _DEFINE_SPEC(0, is_integral, wchar_t, true)
119169691Skan#endif
120169691Skan  _DEFINE_SPEC(0, is_integral, short, true)
121169691Skan  _DEFINE_SPEC(0, is_integral, unsigned short, true)
122169691Skan  _DEFINE_SPEC(0, is_integral, int, true)
123169691Skan  _DEFINE_SPEC(0, is_integral, unsigned int, true)
124169691Skan  _DEFINE_SPEC(0, is_integral, long, true)
125169691Skan  _DEFINE_SPEC(0, is_integral, unsigned long, true)
126169691Skan  _DEFINE_SPEC(0, is_integral, long long, true)
127169691Skan  _DEFINE_SPEC(0, is_integral, unsigned long long, true)
128169691Skan
129169691Skan  template<typename>
130169691Skan    struct is_floating_point
131169691Skan    : public false_type { };
132169691Skan  _DEFINE_SPEC(0, is_floating_point, float, true)
133169691Skan  _DEFINE_SPEC(0, is_floating_point, double, true)
134169691Skan  _DEFINE_SPEC(0, is_floating_point, long double, true)
135169691Skan
136169691Skan  template<typename>
137169691Skan    struct is_array
138169691Skan    : public false_type { };
139169691Skan
140169691Skan  template<typename _Tp, std::size_t _Size>
141169691Skan    struct is_array<_Tp[_Size]>
142169691Skan    : public true_type { };
143169691Skan
144169691Skan  template<typename _Tp>
145169691Skan    struct is_array<_Tp[]>
146169691Skan    : public true_type { };
147169691Skan
148169691Skan  template<typename>
149169691Skan    struct is_pointer
150169691Skan    : public false_type { };
151169691Skan  _DEFINE_SPEC(1, is_pointer, _Tp*, true)
152169691Skan 
153169691Skan  template<typename>
154169691Skan    struct is_reference
155169691Skan    : public false_type { };
156169691Skan
157169691Skan  template<typename _Tp>
158169691Skan    struct is_reference<_Tp&>
159169691Skan    : public true_type { };
160169691Skan
161169691Skan  template<typename>
162169691Skan    struct is_member_object_pointer
163169691Skan    : public false_type { };
164169691Skan  _DEFINE_SPEC(2, is_member_object_pointer, _Tp _Cp::*,
165169691Skan	       !is_function<_Tp>::value)
166169691Skan
167169691Skan  template<typename>
168169691Skan    struct is_member_function_pointer
169169691Skan    : public false_type { };
170169691Skan  _DEFINE_SPEC(2, is_member_function_pointer, _Tp _Cp::*,
171169691Skan	       is_function<_Tp>::value)
172169691Skan
173169691Skan  template<typename _Tp>
174169691Skan    struct is_enum
175169691Skan    : public integral_constant<bool, !(is_fundamental<_Tp>::value
176169691Skan				       || is_array<_Tp>::value
177169691Skan				       || is_pointer<_Tp>::value
178169691Skan				       || is_reference<_Tp>::value
179169691Skan				       || is_member_pointer<_Tp>::value
180169691Skan				       || is_function<_Tp>::value
181169691Skan				       || __is_union_or_class<_Tp>::value)>
182169691Skan    { };
183169691Skan
184169691Skan  template<typename>
185169691Skan    struct is_union { };
186169691Skan
187169691Skan  template<typename>
188169691Skan    struct is_class { };
189169691Skan
190169691Skan  template<typename _Tp>
191169691Skan    struct is_function
192169691Skan    : public integral_constant<bool, !(__in_array<_Tp>::__value
193169691Skan				       || __is_union_or_class<_Tp>::value
194169691Skan				       || is_reference<_Tp>::value
195169691Skan				       || is_void<_Tp>::value)>
196169691Skan    { };
197169691Skan
198169691Skan  /// @brief  composite type traits [4.5.2].
199169691Skan  template<typename _Tp>
200169691Skan    struct is_arithmetic
201169691Skan    : public integral_constant<bool, (is_integral<_Tp>::value
202169691Skan				      || is_floating_point<_Tp>::value)>
203169691Skan    { };
204169691Skan
205169691Skan  template<typename _Tp>
206169691Skan    struct is_fundamental
207169691Skan    : public integral_constant<bool, (is_arithmetic<_Tp>::value
208169691Skan				      || is_void<_Tp>::value)>
209169691Skan    { };
210169691Skan
211169691Skan  template<typename _Tp>
212169691Skan    struct is_object
213169691Skan    : public integral_constant<bool, !(is_function<_Tp>::value
214169691Skan				       || is_reference<_Tp>::value
215169691Skan				       || is_void<_Tp>::value)>
216169691Skan    { };
217169691Skan
218169691Skan  template<typename _Tp>
219169691Skan    struct is_scalar
220169691Skan    : public integral_constant<bool, (is_arithmetic<_Tp>::value
221169691Skan				      || is_enum<_Tp>::value
222169691Skan				      || is_pointer<_Tp>::value
223169691Skan				      || is_member_pointer<_Tp>::value)>
224169691Skan    { };
225169691Skan
226169691Skan  template<typename _Tp>
227169691Skan    struct is_compound
228169691Skan    : public integral_constant<bool, !is_fundamental<_Tp>::value> { };
229169691Skan
230169691Skan  template<typename _Tp>
231169691Skan    struct is_member_pointer
232169691Skan    : public integral_constant<bool,
233169691Skan			       (is_member_object_pointer<_Tp>::value
234169691Skan				|| is_member_function_pointer<_Tp>::value)>
235169691Skan    { };
236169691Skan
237169691Skan  template<typename _Tp>
238169691Skan    struct __is_union_or_class_helper
239169691Skan    : public __sfinae_types
240169691Skan    {
241169691Skan    private:
242169691Skan      template<typename _Up>
243169691Skan        static __one __test(int _Up::*);
244169691Skan      template<typename>
245169691Skan        static __two __test(...);
246169691Skan    
247169691Skan    public:
248169691Skan      static const bool __value = sizeof(__test<_Tp>(0)) == 1;
249169691Skan    };
250169691Skan
251169691Skan  // Extension.
252169691Skan  template<typename _Tp>
253169691Skan    struct __is_union_or_class
254169691Skan    : public integral_constant<bool, __is_union_or_class_helper<_Tp>::__value>
255169691Skan    { };
256169691Skan  
257169691Skan  /// @brief  type properties [4.5.3].
258169691Skan  template<typename>
259169691Skan    struct is_const
260169691Skan    : public false_type { };
261169691Skan
262169691Skan  template<typename _Tp>
263169691Skan    struct is_const<_Tp const>
264169691Skan    : public true_type { };
265169691Skan  
266169691Skan  template<typename>
267169691Skan    struct is_volatile
268169691Skan    : public false_type { };
269169691Skan
270169691Skan  template<typename _Tp>
271169691Skan    struct is_volatile<_Tp volatile>
272169691Skan    : public true_type { };
273169691Skan
274169691Skan  template<typename _Tp>
275169691Skan    struct is_pod
276169691Skan    : public integral_constant<bool, (is_void<_Tp>::value
277169691Skan				      || is_scalar<typename
278169691Skan				      remove_all_extents<_Tp>::type>::value)>
279169691Skan    { };
280169691Skan
281169691Skan  // NB: Without compiler support we cannot tell union from class types,
282169691Skan  // and is_empty and is_polymorphic don't work at all with the former. 
283169691Skan  template<typename _Tp, bool = !__is_union_or_class<_Tp>::value>
284169691Skan    struct __is_empty_helper
285169691Skan    { 
286169691Skan    private:
287169691Skan      template<typename>
288169691Skan        struct __first { };
289169691Skan      template<typename _Up>
290169691Skan        struct __second
291169691Skan        : public _Up { };
292169691Skan           
293169691Skan    public:
294169691Skan      static const bool __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>);
295169691Skan    };
296169691Skan
297169691Skan  template<typename _Tp>
298169691Skan    struct __is_empty_helper<_Tp, true>
299169691Skan    { static const bool __value = false; };
300169691Skan
301169691Skan  template<typename _Tp>
302169691Skan    struct is_empty
303169691Skan    : public integral_constant<bool, __is_empty_helper<_Tp>::__value>
304169691Skan    { };
305169691Skan
306169691Skan  template<typename _Tp, bool = !__is_union_or_class<_Tp>::value>
307169691Skan    struct __is_polymorphic_helper
308169691Skan    { 
309169691Skan    private:
310169691Skan      template<typename _Up>
311169691Skan        struct __first
312169691Skan        : public _Up { };
313169691Skan      template<typename _Up>
314169691Skan        struct __second
315169691Skan        : public _Up
316169691Skan	{ 
317169691Skan	  virtual void __dummy();
318169691Skan	  virtual ~__second() throw();
319169691Skan	};
320169691Skan
321169691Skan    public:
322169691Skan      static const bool __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>);
323169691Skan    };
324169691Skan
325169691Skan  template<typename _Tp>
326169691Skan    struct __is_polymorphic_helper<_Tp, true>
327169691Skan    { static const bool __value = false; };
328169691Skan
329169691Skan  template<typename _Tp>
330169691Skan    struct is_polymorphic
331169691Skan    : public integral_constant<bool, __is_polymorphic_helper<_Tp>::__value>
332169691Skan    { };
333169691Skan
334169691Skan  // Exploit the resolution DR core/337.
335169691Skan  template<typename _Tp>
336169691Skan    struct is_abstract
337169691Skan    : public integral_constant<bool, (!__in_array<_Tp>::__value
338169691Skan				      && __is_union_or_class<_Tp>::value)> { };
339169691Skan
340169691Skan  template<typename _Tp>
341169691Skan    struct has_trivial_constructor
342169691Skan    : public integral_constant<bool, is_pod<_Tp>::value> { };
343169691Skan
344169691Skan  template<typename _Tp>
345169691Skan    struct has_trivial_copy
346169691Skan    : public integral_constant<bool, is_pod<_Tp>::value> { };
347169691Skan
348169691Skan  template<typename _Tp>
349169691Skan    struct has_trivial_assign
350169691Skan    : public integral_constant<bool, is_pod<_Tp>::value> { };
351169691Skan
352169691Skan  template<typename _Tp>
353169691Skan    struct has_trivial_destructor
354169691Skan    : public integral_constant<bool, is_pod<_Tp>::value> { };
355169691Skan
356169691Skan  template<typename _Tp>
357169691Skan    struct has_nothrow_constructor
358169691Skan    : public integral_constant<bool, is_pod<_Tp>::value> { };
359169691Skan
360169691Skan  template<typename _Tp>
361169691Skan    struct has_nothrow_copy
362169691Skan    : public integral_constant<bool, is_pod<_Tp>::value> { };
363169691Skan
364169691Skan  template<typename _Tp>
365169691Skan    struct has_nothrow_assign
366169691Skan    : public integral_constant<bool, is_pod<_Tp>::value> { };
367169691Skan
368169691Skan  template<typename>
369169691Skan    struct has_virtual_destructor
370169691Skan    : public false_type { };
371169691Skan
372169691Skan  template<typename>
373169691Skan    struct is_signed
374169691Skan    : public false_type { };
375169691Skan  _DEFINE_SPEC(0, is_signed, signed char, true)
376169691Skan  _DEFINE_SPEC(0, is_signed, short, true)
377169691Skan  _DEFINE_SPEC(0, is_signed, int, true)
378169691Skan  _DEFINE_SPEC(0, is_signed, long, true)
379169691Skan  _DEFINE_SPEC(0, is_signed, long long, true)
380169691Skan
381169691Skan  template<typename>
382169691Skan    struct is_unsigned
383169691Skan    : public false_type { };
384169691Skan  _DEFINE_SPEC(0, is_unsigned, unsigned char, true)
385169691Skan  _DEFINE_SPEC(0, is_unsigned, unsigned short, true)
386169691Skan  _DEFINE_SPEC(0, is_unsigned, unsigned int, true)
387169691Skan  _DEFINE_SPEC(0, is_unsigned, unsigned long, true)
388169691Skan  _DEFINE_SPEC(0, is_unsigned, unsigned long long, true)
389169691Skan
390169691Skan  template<typename _Tp>
391169691Skan    struct alignment_of
392169691Skan    : public integral_constant<std::size_t, __alignof__(_Tp)> { };
393169691Skan  
394169691Skan  template<typename>
395169691Skan    struct rank
396169691Skan    : public integral_constant<std::size_t, 0> { };
397169691Skan   
398169691Skan  template<typename _Tp, std::size_t _Size>
399169691Skan    struct rank<_Tp[_Size]>
400169691Skan    : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
401169691Skan
402169691Skan  template<typename _Tp>
403169691Skan    struct rank<_Tp[]>
404169691Skan    : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
405169691Skan   
406169691Skan  template<typename, unsigned>
407169691Skan    struct extent
408169691Skan    : public integral_constant<std::size_t, 0> { };
409169691Skan  
410169691Skan  template<typename _Tp, unsigned _Uint, std::size_t _Size>
411169691Skan    struct extent<_Tp[_Size], _Uint>
412169691Skan    : public integral_constant<std::size_t,
413169691Skan			       _Uint == 0 ? _Size : extent<_Tp,
414169691Skan							   _Uint - 1>::value>
415169691Skan    { };
416169691Skan
417169691Skan  template<typename _Tp, unsigned _Uint>
418169691Skan    struct extent<_Tp[], _Uint>
419169691Skan    : public integral_constant<std::size_t,
420169691Skan			       _Uint == 0 ? 0 : extent<_Tp,
421169691Skan						       _Uint - 1>::value>
422169691Skan    { };
423169691Skan  
424169691Skan  /// @brief  relationships between types [4.6].
425169691Skan  template<typename, typename>
426169691Skan    struct is_same
427169691Skan    : public false_type { };
428169691Skan
429169691Skan  template<typename _Tp>
430169691Skan    struct is_same<_Tp, _Tp>
431169691Skan    : public true_type { };
432169691Skan
433169691Skan  // See Daveed Vandevoorde explanation in http://tinyurl.com/502f.
434169691Skan  // Also see Rani Sharoni in http://tinyurl.com/6jvyq.
435169691Skan  template<typename _Base, typename _Derived,
436169691Skan	   bool = (!__is_union_or_class<_Base>::value
437169691Skan		   || !__is_union_or_class<_Derived>::value
438169691Skan		   || is_same<_Base, _Derived>::value)>
439169691Skan    struct __is_base_of_helper
440169691Skan    : public __sfinae_types
441169691Skan    {
442169691Skan    private:
443169691Skan      typedef typename remove_cv<_Base>::type     _NoCv_Base;      
444169691Skan      typedef typename remove_cv<_Derived>::type  _NoCv_Derived;
445169691Skan      
446169691Skan      template<typename _Up>
447169691Skan        static __one __test(_NoCv_Derived&, _Up);
448169691Skan      static __two __test(_NoCv_Base&, int);
449169691Skan   
450169691Skan      struct _Conv
451169691Skan      {
452169691Skan	operator _NoCv_Derived&();
453169691Skan	operator _NoCv_Base&() const;
454169691Skan      };
455169691Skan   
456169691Skan    public:
457169691Skan      static const bool __value = sizeof(__test(_Conv(), 0)) == 1;
458169691Skan    };
459169691Skan
460169691Skan  template<typename _Base, typename _Derived>
461169691Skan    struct __is_base_of_helper<_Base, _Derived, true>
462169691Skan    { static const bool __value = is_same<_Base, _Derived>::value; };
463169691Skan
464169691Skan  template<typename _Base, typename _Derived>
465169691Skan    struct is_base_of
466169691Skan    : public integral_constant<bool,
467169691Skan			       __is_base_of_helper<_Base, _Derived>::__value>
468169691Skan    { };
469169691Skan
470169691Skan  template<typename _From, typename _To>
471169691Skan    struct __is_convertible_simple
472169691Skan    : public __sfinae_types
473169691Skan    {
474169691Skan    private:
475169691Skan      static __one __test(_To);
476169691Skan      static __two __test(...);
477169691Skan      static _From __makeFrom();
478169691Skan    
479169691Skan    public:
480169691Skan      static const bool __value = sizeof(__test(__makeFrom())) == 1;
481169691Skan    };
482169691Skan
483169691Skan  template<typename _Tp>
484169691Skan    struct __is_int_or_cref
485169691Skan    {
486169691Skan      typedef typename remove_reference<_Tp>::type __rr_Tp;
487169691Skan      static const bool __value = (is_integral<_Tp>::value
488169691Skan				   || (is_integral<__rr_Tp>::value
489169691Skan				       && is_const<__rr_Tp>::value
490169691Skan				       && !is_volatile<__rr_Tp>::value));
491169691Skan    };
492169691Skan
493169691Skan  template<typename _From, typename _To,
494169691Skan	   bool = (is_void<_From>::value || is_void<_To>::value
495169691Skan		   || is_function<_To>::value || is_array<_To>::value
496169691Skan		   // This special case is here only to avoid warnings.		   
497169691Skan		   || (is_floating_point<typename
498169691Skan		       remove_reference<_From>::type>::value
499169691Skan		       && __is_int_or_cref<_To>::__value))>
500169691Skan    struct __is_convertible_helper
501169691Skan    {
502169691Skan      // "An imaginary lvalue of type From...".
503169691Skan      static const bool __value = (__is_convertible_simple<typename
504169691Skan				   add_reference<_From>::type, _To>::__value);
505169691Skan    };
506169691Skan
507169691Skan  template<typename _From, typename _To>
508169691Skan    struct __is_convertible_helper<_From, _To, true>
509169691Skan    { static const bool __value = (is_void<_To>::value
510169691Skan				   || (__is_int_or_cref<_To>::__value
511169691Skan				       && !is_void<_From>::value)); };
512169691Skan
513169691Skan  template<typename _From, typename _To>
514169691Skan    struct is_convertible
515169691Skan    : public integral_constant<bool,
516169691Skan			       __is_convertible_helper<_From, _To>::__value>
517169691Skan    { };
518169691Skan
519169691Skan  /// @brief  const-volatile modifications [4.7.1].
520169691Skan  template<typename _Tp>
521169691Skan    struct remove_const
522169691Skan    { typedef _Tp     type; };
523169691Skan
524169691Skan  template<typename _Tp>
525169691Skan    struct remove_const<_Tp const>
526169691Skan    { typedef _Tp     type; };
527169691Skan  
528169691Skan  template<typename _Tp>
529169691Skan    struct remove_volatile
530169691Skan    { typedef _Tp     type; };
531169691Skan
532169691Skan  template<typename _Tp>
533169691Skan    struct remove_volatile<_Tp volatile>
534169691Skan    { typedef _Tp     type; };
535169691Skan  
536169691Skan  template<typename _Tp>
537169691Skan    struct remove_cv
538169691Skan    {
539169691Skan      typedef typename
540169691Skan      remove_const<typename remove_volatile<_Tp>::type>::type     type;
541169691Skan    };
542169691Skan  
543169691Skan  template<typename _Tp>
544169691Skan    struct add_const
545169691Skan    { typedef _Tp const     type; };
546169691Skan   
547169691Skan  template<typename _Tp>
548169691Skan    struct add_volatile
549169691Skan    { typedef _Tp volatile     type; };
550169691Skan  
551169691Skan  template<typename _Tp>
552169691Skan    struct add_cv
553169691Skan    {
554169691Skan      typedef typename
555169691Skan      add_const<typename add_volatile<_Tp>::type>::type     type;
556169691Skan    };
557169691Skan
558169691Skan  /// @brief  reference modifications [4.7.2].
559169691Skan  template<typename _Tp>
560169691Skan    struct remove_reference
561169691Skan    { typedef _Tp     type; };
562169691Skan
563169691Skan  template<typename _Tp>
564169691Skan    struct remove_reference<_Tp&>
565169691Skan    { typedef _Tp     type; };
566169691Skan
567169691Skan  // NB: Careful with reference to void.
568169691Skan  template<typename _Tp, bool = (is_void<_Tp>::value
569169691Skan				 || is_reference<_Tp>::value)>
570169691Skan    struct __add_reference_helper
571169691Skan    { typedef _Tp&    type; };
572169691Skan
573169691Skan  template<typename _Tp>
574169691Skan    struct __add_reference_helper<_Tp, true>
575169691Skan    { typedef _Tp     type; };
576169691Skan
577169691Skan  template<typename _Tp>
578169691Skan    struct add_reference
579169691Skan    : public __add_reference_helper<_Tp>
580169691Skan    { };
581169691Skan
582169691Skan  /// @brief  array modifications [4.7.3].
583169691Skan  template<typename _Tp>
584169691Skan    struct remove_extent
585169691Skan    { typedef _Tp     type; };
586169691Skan
587169691Skan  template<typename _Tp, std::size_t _Size>
588169691Skan    struct remove_extent<_Tp[_Size]>
589169691Skan    { typedef _Tp     type; };
590169691Skan
591169691Skan  template<typename _Tp>
592169691Skan    struct remove_extent<_Tp[]>
593169691Skan    { typedef _Tp     type; };
594169691Skan
595169691Skan  template<typename _Tp>
596169691Skan    struct remove_all_extents
597169691Skan    { typedef _Tp     type; };
598169691Skan
599169691Skan  template<typename _Tp, std::size_t _Size>
600169691Skan    struct remove_all_extents<_Tp[_Size]>
601169691Skan    { typedef typename remove_all_extents<_Tp>::type     type; };
602169691Skan
603169691Skan  template<typename _Tp>
604169691Skan    struct remove_all_extents<_Tp[]>
605169691Skan    { typedef typename remove_all_extents<_Tp>::type     type; };
606169691Skan
607169691Skan  /// @brief  pointer modifications [4.7.4].
608169691Skan#undef _DEFINE_SPEC_BODY
609169691Skan#define _DEFINE_SPEC_BODY(_Value)      \
610169691Skan    { typedef _Tp     type; };
611169691Skan
612169691Skan  template<typename _Tp>
613169691Skan    struct remove_pointer
614169691Skan    { typedef _Tp     type; };
615169691Skan  _DEFINE_SPEC(1, remove_pointer, _Tp*, false)
616169691Skan  
617169691Skan  template<typename _Tp>
618169691Skan    struct add_pointer
619169691Skan    { typedef typename remove_reference<_Tp>::type*     type; };
620169691Skan
621169691Skan  /// @brief  other transformations [4.8].
622169691Skan  
623169691Skan  // Due to c++/19163 and c++/17743, for the time being we cannot use
624169691Skan  // the correct, neat implementation :-(
625169691Skan  // 
626169691Skan  // template<std::size_t _Len, std::size_t _Align>
627169691Skan  //   struct aligned_storage
628169691Skan  //   { typedef char type[_Len] __attribute__((__aligned__(_Align))); }
629169691Skan  //
630169691Skan  // Temporary workaround, useful for Align up to 32:
631169691Skan  template<std::size_t, std::size_t>
632169691Skan    struct aligned_storage { };
633169691Skan
634169691Skan  template<std::size_t _Len>
635169691Skan    struct aligned_storage<_Len, 1>
636169691Skan    {
637169691Skan      union type
638169691Skan      {
639169691Skan	unsigned char __data[_Len];
640169691Skan	char __align __attribute__((__aligned__(1)));
641169691Skan      };
642169691Skan    };
643169691Skan
644169691Skan  template<std::size_t _Len>
645169691Skan    struct aligned_storage<_Len, 2>
646169691Skan    {
647169691Skan      union type
648169691Skan      {
649169691Skan	unsigned char __data[_Len];
650169691Skan	char __align __attribute__((__aligned__(2)));
651169691Skan      };
652169691Skan    };
653169691Skan
654169691Skan  template<std::size_t _Len>
655169691Skan    struct aligned_storage<_Len, 4>
656169691Skan    {
657169691Skan      union type
658169691Skan      {
659169691Skan	unsigned char __data[_Len];
660169691Skan	char __align __attribute__((__aligned__(4)));
661169691Skan      };
662169691Skan    };
663169691Skan
664169691Skan  template<std::size_t _Len>
665169691Skan    struct aligned_storage<_Len, 8>
666169691Skan    {
667169691Skan      union type
668169691Skan      {
669169691Skan	unsigned char __data[_Len];
670169691Skan	char __align __attribute__((__aligned__(8)));
671169691Skan      };
672169691Skan    };
673169691Skan
674169691Skan  template<std::size_t _Len>
675169691Skan    struct aligned_storage<_Len, 16>
676169691Skan    {
677169691Skan      union type
678169691Skan      {
679169691Skan	unsigned char __data[_Len];
680169691Skan	char __align __attribute__((__aligned__(16)));
681169691Skan      };
682169691Skan    };
683169691Skan  
684169691Skan  template<std::size_t _Len>
685169691Skan    struct aligned_storage<_Len, 32>
686169691Skan    {
687169691Skan      union type
688169691Skan      {
689169691Skan	unsigned char __data[_Len];
690169691Skan	char __align __attribute__((__aligned__(32)));
691169691Skan      };
692169691Skan    };
693169691Skan
694169691Skan#undef _DEFINE_SPEC_0_HELPER
695169691Skan#undef _DEFINE_SPEC_1_HELPER
696169691Skan#undef _DEFINE_SPEC_2_HELPER
697169691Skan#undef _DEFINE_SPEC
698169691Skan#undef _DEFINE_SPEC_BODY
699169691Skan
700169691Skan_GLIBCXX_END_NAMESPACE
701169691Skan}
702169691Skan
703169691Skan#endif
704