Patchwork [trans-mem,build] Hack around top-level Makefile libstdc++ breakage

login
register
mail settings
Submitter Richard Henderson
Date Nov. 4, 2011, 5:57 a.m.
Message ID <4EB37ECE.4010807@redhat.com>
Download mbox | patch
Permalink /patch/123569/
State New
Headers show

Comments

Richard Henderson - Nov. 4, 2011, 5:57 a.m.
We currently have a problem building libitm because it uses the libstdc++
header <type_traits>, and the toplevel Makefile passes a single set of
include paths for all multilibs.  In the recent merges from mainline, we
brought in changes to that header that reference __int128_t.

Building for x86_64, we detect that __int128_t is supported for the main
multilib, but when it comes to building the -m32 multilib we do not 
support that type.  With the incorrect include path, we read the wrong
<bits/c++config> file, which leads us to attempt to use __int128_t in
the -m32 libitm multlib, which of course fails.

I've worked for 2 days to try to work out what our Makefile does.  It
seems completely and totally broken to me.  I can't imagine there's a
quick fix, but I'd be delighted to be proven wrong.

This has never come up before because there are no other runtime
libraries that actually use libstdc++ -- merely make some use of the
c++ compiler.  The top-level makefile bits have never ever been used.

My "fix" is to take the one file that we really needed and copy it into
the libitm directory, suitably edited so that it doesn't need all of
the other c++config stuff.

If and when the top-level build is fixed, we can simply remove the copy.

Committed.


r~
* local_type_traits: New file.
	* libitm_i.h: Use it.  Use C headers, not C++ wrappers.
Joseph S. Myers - Nov. 4, 2011, 12:32 p.m.
On Thu, 3 Nov 2011, Richard Henderson wrote:

> I've worked for 2 days to try to work out what our Makefile does.  It
> seems completely and totally broken to me.  I can't imagine there's a
> quick fix, but I'd be delighted to be proven wrong.

It would be fixed by staged install (install into a temporary directory 
within the build tree, run the compilers from there relying on 
relocatability so that only the install to the staging directory and 
nothing else needs to know how to put pieces together from their build 
tree locations), but that is anything but a quick fix (probably months of 
work)....
Alexandre Oliva - Nov. 4, 2011, 12:44 p.m.
On Nov  4, 2011, Richard Henderson <rth@redhat.com> wrote:

> I can't imagine there's a quick fix, but I'd be delighted to be proven
> wrong.

I don't have a patch yet, but IMHO the correct and quick-ish fix would
be in config-ml.in: get it to apply the same transformation to CC et al
that it applies at configure time in the multi-do: fragment it adds to
the Makefile.  I'm not quite sure how to introduce that yet, but that's
what I'm trying to figure out now.
DJ Delorie - Nov. 4, 2011, 3:53 p.m.
If libstdc++ has multilib-specific headers, which one gets installed?
How will anything be able to use those headers from an installed tree?
Richard Henderson - Nov. 4, 2011, 4 p.m.
On 11/04/2011 05:32 AM, Joseph S. Myers wrote:
> It would be fixed by staged install ...

Yeah, I thought of that too.  Maybe for 4.8...


r~
H.J. Lu - Nov. 4, 2011, 4:12 p.m.
On Thu, Nov 3, 2011 at 10:57 PM, Richard Henderson <rth@redhat.com> wrote:
> We currently have a problem building libitm because it uses the libstdc++
> header <type_traits>, and the toplevel Makefile passes a single set of
> include paths for all multilibs.  In the recent merges from mainline, we
> brought in changes to that header that reference __int128_t.
>
> Building for x86_64, we detect that __int128_t is supported for the main
> multilib, but when it comes to building the -m32 multilib we do not
> support that type.  With the incorrect include path, we read the wrong
> <bits/c++config> file, which leads us to attempt to use __int128_t in
> the -m32 libitm multlib, which of course fails.
>

I believe that C++ tests pick the correct bits/c++config for -m32. Can't
libitm do something similar?
DJ Delorie - Nov. 4, 2011, 4:19 p.m.
> I believe that C++ tests pick the correct bits/c++config for
> -m32. Can't libitm do something similar?

The problem is that the -I for the build is chosen at the toplevel,
*before* iterating over the multilibs, whereas the -I for testing is
chosen in dejagnu, *after* iterating over the multilibs.

This, despite the toplevel *build* flags coming from
"libstdc++-v3/scripts/testsuite_flags" (which returns different
results for each multilib).

Patch

diff --git a/libitm/libitm_i.h b/libitm/libitm_i.h
index 746f7b3..3729a31 100644
--- a/libitm/libitm_i.h
+++ b/libitm/libitm_i.h
@@ -32,11 +32,11 @@ 
 #include "libitm.h"
 #include "config.h"
 
-#include <cassert>
-#include <cstdlib>
-#include <cstring>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unwind.h>
-#include <type_traits>
+#include "local_type_traits"
 
 #include "common.h"
 
diff --git a/libitm/local_type_traits b/libitm/local_type_traits
new file mode 100644
index 0000000..8349cd5
--- /dev/null
+++ b/libitm/local_type_traits
@@ -0,0 +1,1901 @@ 
+// C++0x type_traits -*- C++ -*-
+
+// Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+// ????????????????????????????????????????????????????????????????????
+//
+// This is a copy of the libstdc++ header, with the trivial modification
+// of ignoring the c++config.h include.  If and when the top-level build is
+// fixed so that target libraries can be built using the newly built, we can
+// delete this file.
+//
+// ????????????????????????????????????????????????????????????????????
+
+/** @file include/type_traits
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TYPE_TRAITS
+#define _GLIBCXX_TYPE_TRAITS 1
+
+// #pragma GCC system_header
+
+// #ifndef __GXX_EXPERIMENTAL_CXX0X__
+// # include <bits/c++0x_warning.h>
+// #else
+// #include <bits/c++config.h>
+
+namespace std // _GLIBCXX_VISIBILITY(default)
+{
+// _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /**
+   * @addtogroup metaprogramming
+   * @{
+   */
+
+  /// integral_constant
+  template<typename _Tp, _Tp __v>
+    struct integral_constant
+    {
+      static constexpr _Tp                  value = __v;
+      typedef _Tp                           value_type;
+      typedef integral_constant<_Tp, __v>   type;
+      constexpr operator value_type() { return value; }
+    };
+  
+  /// typedef for true_type
+  typedef integral_constant<bool, true>     true_type;
+
+  /// typedef for false_type
+  typedef integral_constant<bool, false>    false_type;
+
+  template<typename _Tp, _Tp __v>
+    constexpr _Tp integral_constant<_Tp, __v>::value;
+
+  // Meta programming helper types.
+
+  template<bool, typename, typename>
+    struct conditional;
+
+  template<typename...>
+    struct __or_;
+
+  template<>
+    struct __or_<>
+    : public false_type
+    { };
+
+  template<typename _B1>
+    struct __or_<_B1>
+    : public _B1
+    { };
+
+  template<typename _B1, typename _B2>
+    struct __or_<_B1, _B2>
+    : public conditional<_B1::value, _B1, _B2>::type
+    { };
+
+  template<typename _B1, typename _B2, typename _B3, typename... _Bn>
+    struct __or_<_B1, _B2, _B3, _Bn...>
+    : public conditional<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>::type
+    { };
+
+  template<typename...>
+    struct __and_;
+
+  template<>
+    struct __and_<>
+    : public true_type
+    { };
+
+  template<typename _B1>
+    struct __and_<_B1>
+    : public _B1
+    { };
+
+  template<typename _B1, typename _B2>
+    struct __and_<_B1, _B2>
+    : public conditional<_B1::value, _B2, _B1>::type
+    { };
+
+  template<typename _B1, typename _B2, typename _B3, typename... _Bn>
+    struct __and_<_B1, _B2, _B3, _Bn...>
+    : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type
+    { };
+
+  template<typename _Pp>
+    struct __not_
+    : public integral_constant<bool, !_Pp::value>
+    { };
+
+  struct __sfinae_types
+  {
+    typedef char __one;
+    typedef struct { char __arr[2]; } __two;
+  };
+
+  // primary type categories.
+
+  template<typename>
+    struct remove_cv;
+
+  template<typename>
+    struct __is_void_helper
+    : public false_type { };
+
+  template<>
+    struct __is_void_helper<void>
+    : public true_type { };
+
+  /// is_void
+  template<typename _Tp>
+    struct is_void
+    : public integral_constant<bool, (__is_void_helper<typename
+				      remove_cv<_Tp>::type>::value)>
+    { };
+
+  template<typename>
+    struct __is_integral_helper
+    : public false_type { };
+
+  template<>
+    struct __is_integral_helper<bool>
+    : public true_type { };
+  
+  template<>
+    struct __is_integral_helper<char>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<signed char>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned char>
+    : public true_type { };
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template<>
+    struct __is_integral_helper<wchar_t>
+    : public true_type { };
+#endif
+
+  template<>
+    struct __is_integral_helper<char16_t>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<char32_t>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<short>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned short>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<int>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned int>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<long>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned long>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<long long>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned long long>
+    : public true_type { };
+
+#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+  template<>
+    struct __is_integral_helper<__int128>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned __int128>
+    : public true_type { };
+#endif
+
+  /// is_integral
+  template<typename _Tp>
+    struct is_integral
+    : public integral_constant<bool, (__is_integral_helper<typename
+				      remove_cv<_Tp>::type>::value)>
+    { };
+
+  template<typename>
+    struct __is_floating_point_helper
+    : public false_type { };
+
+  template<>
+    struct __is_floating_point_helper<float>
+    : public true_type { };
+
+  template<>
+    struct __is_floating_point_helper<double>
+    : public true_type { };
+
+  template<>
+    struct __is_floating_point_helper<long double>
+    : public true_type { };
+
+#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
+  template<>
+    struct __is_floating_point_helper<__float128>
+    : public true_type { };
+#endif
+
+  /// is_floating_point
+  template<typename _Tp>
+    struct is_floating_point
+    : public integral_constant<bool, (__is_floating_point_helper<typename
+				      remove_cv<_Tp>::type>::value)>
+    { };
+
+  /// is_array
+  template<typename>
+    struct is_array
+    : public false_type { };
+
+  template<typename _Tp, size_t _Size>
+    struct is_array<_Tp[_Size]>
+    : public true_type { };
+
+  template<typename _Tp>
+    struct is_array<_Tp[]>
+    : public true_type { };
+
+  template<typename>
+    struct __is_pointer_helper
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_pointer_helper<_Tp*>
+    : public true_type { };
+
+  /// is_pointer
+  template<typename _Tp>
+    struct is_pointer
+    : public integral_constant<bool, (__is_pointer_helper<typename
+				      remove_cv<_Tp>::type>::value)>
+    { };
+
+  /// is_lvalue_reference
+  template<typename>
+    struct is_lvalue_reference
+    : public false_type { };
+
+  template<typename _Tp>
+    struct is_lvalue_reference<_Tp&>
+    : public true_type { };
+
+  /// is_rvalue_reference
+  template<typename>
+    struct is_rvalue_reference
+    : public false_type { };
+
+  template<typename _Tp>
+    struct is_rvalue_reference<_Tp&&>
+    : public true_type { };
+
+  template<typename>
+    struct is_function;
+
+  template<typename>
+    struct __is_member_object_pointer_helper
+    : public false_type { };
+
+  template<typename _Tp, typename _Cp>
+    struct __is_member_object_pointer_helper<_Tp _Cp::*>
+    : public integral_constant<bool, !is_function<_Tp>::value> { };
+
+  /// is_member_object_pointer
+  template<typename _Tp>
+    struct is_member_object_pointer
+    : public integral_constant<bool, (__is_member_object_pointer_helper<
+				      typename remove_cv<_Tp>::type>::value)>
+    { };
+
+  template<typename>
+    struct __is_member_function_pointer_helper
+    : public false_type { };
+
+  template<typename _Tp, typename _Cp>
+    struct __is_member_function_pointer_helper<_Tp _Cp::*>
+    : public integral_constant<bool, is_function<_Tp>::value> { };
+
+  /// is_member_function_pointer
+  template<typename _Tp>
+    struct is_member_function_pointer
+    : public integral_constant<bool, (__is_member_function_pointer_helper<
+				      typename remove_cv<_Tp>::type>::value)>
+    { };
+
+  /// is_enum
+  template<typename _Tp>
+    struct is_enum
+    : public integral_constant<bool, __is_enum(_Tp)>
+    { };
+
+  /// is_union
+  template<typename _Tp>
+    struct is_union
+    : public integral_constant<bool, __is_union(_Tp)>
+    { };
+
+  /// is_class
+  template<typename _Tp>
+    struct is_class
+    : public integral_constant<bool, __is_class(_Tp)>
+    { };
+
+  /// is_function
+  template<typename>
+    struct is_function
+    : public false_type { };
+
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes...)>
+    : public true_type { };
+
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes......)>
+    : public true_type { };
+
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes...) const>
+    : public true_type { };
+
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes......) const>
+    : public true_type { };
+
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes...) volatile>
+    : public true_type { };
+
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes......) volatile>
+    : public true_type { };
+
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes...) const volatile>
+    : public true_type { };
+
+  template<typename _Res, typename... _ArgTypes>
+    struct is_function<_Res(_ArgTypes......) const volatile>
+    : public true_type { };
+
+  template<typename>
+    struct __is_nullptr_t_helper
+    : public false_type { };
+
+#if 0
+  template<>
+    struct __is_nullptr_t_helper<nullptr_t>
+    : public true_type { };
+#endif
+
+  // __is_nullptr_t (extension).
+  template<typename _Tp>
+    struct __is_nullptr_t
+    : public integral_constant<bool, (__is_nullptr_t_helper<typename
+				      remove_cv<_Tp>::type>::value)>
+    { };
+
+  // composite type categories.
+
+  /// is_reference
+  template<typename _Tp>
+    struct is_reference
+    : public __or_<is_lvalue_reference<_Tp>,
+                   is_rvalue_reference<_Tp>>::type
+    { };
+
+  /// is_arithmetic
+  template<typename _Tp>
+    struct is_arithmetic
+    : public __or_<is_integral<_Tp>, is_floating_point<_Tp>>::type
+    { };
+
+  /// is_fundamental
+  template<typename _Tp>
+    struct is_fundamental
+    : public __or_<is_arithmetic<_Tp>, is_void<_Tp>>::type
+    { };
+
+  /// is_object
+  template<typename _Tp>
+    struct is_object
+    : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
+                          is_void<_Tp>>>::type
+    { };
+
+  template<typename>
+    struct is_member_pointer;
+
+  /// is_scalar
+  template<typename _Tp>
+    struct is_scalar
+    : public __or_<is_arithmetic<_Tp>, is_enum<_Tp>, is_pointer<_Tp>,
+                   is_member_pointer<_Tp>, __is_nullptr_t<_Tp>>::type
+    { };
+
+  /// is_compound
+  template<typename _Tp>
+    struct is_compound
+    : public integral_constant<bool, !is_fundamental<_Tp>::value> { };
+
+  /// is_member_pointer
+  template<typename _Tp>
+    struct __is_member_pointer_helper
+    : public false_type { };
+
+  template<typename _Tp, typename _Cp>
+    struct __is_member_pointer_helper<_Tp _Cp::*>
+    : public true_type { };
+
+  template<typename _Tp>
+    struct is_member_pointer
+    : public integral_constant<bool, (__is_member_pointer_helper<
+				      typename remove_cv<_Tp>::type>::value)>
+    { };
+
+  // type properties.
+
+  /// is_const
+  template<typename>
+    struct is_const
+    : public false_type { };
+
+  template<typename _Tp>
+    struct is_const<_Tp const>
+    : public true_type { };
+  
+  /// is_volatile
+  template<typename>
+    struct is_volatile
+    : public false_type { };
+
+  template<typename _Tp>
+    struct is_volatile<_Tp volatile>
+    : public true_type { };
+
+  /// is_trivial
+  template<typename _Tp>
+    struct is_trivial
+    : public integral_constant<bool, __is_trivial(_Tp)>
+    { };
+
+  /// is_trivially_copyable (still unimplemented)
+
+  /// is_standard_layout
+  template<typename _Tp>
+    struct is_standard_layout
+    : public integral_constant<bool, __is_standard_layout(_Tp)>
+    { };
+
+  /// is_pod
+  // Could use is_standard_layout && is_trivial instead of the builtin.
+  template<typename _Tp>
+    struct is_pod
+    : public integral_constant<bool, __is_pod(_Tp)>
+    { };
+
+  /// is_literal_type
+  template<typename _Tp>
+    struct is_literal_type
+    : public integral_constant<bool, __is_literal_type(_Tp)>
+    { };
+
+  /// is_empty
+  template<typename _Tp>
+    struct is_empty
+    : public integral_constant<bool, __is_empty(_Tp)>
+    { };
+
+  /// is_polymorphic
+  template<typename _Tp>
+    struct is_polymorphic
+    : public integral_constant<bool, __is_polymorphic(_Tp)>
+    { };
+
+  /// is_abstract
+  template<typename _Tp>
+    struct is_abstract
+    : public integral_constant<bool, __is_abstract(_Tp)>
+    { };
+
+  template<typename _Tp,
+	   bool = is_integral<_Tp>::value,
+	   bool = is_floating_point<_Tp>::value>
+    struct __is_signed_helper
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_signed_helper<_Tp, false, true>
+    : public true_type { };
+
+  template<typename _Tp>
+    struct __is_signed_helper<_Tp, true, false>
+    : public integral_constant<bool, static_cast<bool>(_Tp(-1) < _Tp(0))>
+    { };
+
+  /// is_signed
+  template<typename _Tp>
+    struct is_signed
+    : public integral_constant<bool, __is_signed_helper<_Tp>::value>
+    { };
+
+  /// is_unsigned
+  template<typename _Tp>
+    struct is_unsigned
+    : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type
+    { };
+
+
+  // destructible and constructible type properties
+
+  template<typename>
+    struct add_rvalue_reference;
+
+  template<typename _Tp>
+    typename add_rvalue_reference<_Tp>::type declval() noexcept;
+
+  template<typename, unsigned = 0>
+    struct extent;
+
+  template<typename>
+    struct remove_all_extents;
+
+  template<typename _Tp>
+    struct __is_array_known_bounds
+    : public integral_constant<bool, (extent<_Tp>::value > 0)>
+    { };
+
+  template<typename _Tp>
+    struct __is_array_unknown_bounds
+    : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>::type
+    { };
+    
+  // In N3290 is_destructible does not say anything about function 
+  // types and abstract types, see LWG 2049. This implementation
+  // describes function types as trivially nothrow destructible and
+  // abstract types as destructible, iff the  explicit destructor
+  // call expression is wellformed.
+  struct __do_is_destructible_impl_1
+  {
+    template<typename _Up>
+      struct __w { _Up __u; };
+
+    template<typename _Tp, typename
+             = decltype(declval<__w<_Tp>&>().~__w<_Tp>())>
+      static true_type __test(int);
+
+    template<typename>
+      static false_type __test(...);
+  };
+
+  template<typename _Tp>
+    struct __is_destructible_impl_1
+    : public __do_is_destructible_impl_1
+    {
+      typedef decltype(__test<_Tp>(0)) type;
+    };
+
+  // Special implementation for abstract types
+  struct __do_is_destructible_impl_2
+  {
+    template<typename _Tp, typename = decltype(declval<_Tp&>().~_Tp())>
+      static true_type __test(int);
+
+    template<typename>
+      static false_type __test(...);
+  };
+
+  template<typename _Tp>
+    struct __is_destructible_impl_2
+    : public __do_is_destructible_impl_2
+    {
+      typedef decltype(__test<_Tp>(0)) type;
+    };
+
+  template<typename _Tp,
+           bool = __or_<is_void<_Tp>,
+                        __is_array_unknown_bounds<_Tp>>::value,
+           bool = __or_<is_reference<_Tp>, is_function<_Tp>>::value>
+    struct __is_destructible_safe;
+
+  template<typename _Tp>
+    struct __is_destructible_safe<_Tp, false, false>
+    : public conditional<is_abstract<_Tp>::value,
+			 __is_destructible_impl_2<_Tp>,
+                         __is_destructible_impl_1<_Tp>>::type::type
+    { };
+
+  template<typename _Tp>
+    struct __is_destructible_safe<_Tp, true, false>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_destructible_safe<_Tp, false, true>
+    : public true_type { };
+
+  /// is_destructible
+  template<typename _Tp>
+    struct is_destructible
+    : public integral_constant<bool, (__is_destructible_safe<_Tp>::value)>
+    { };
+
+  struct __do_is_default_constructible_impl
+  {
+    template<typename _Tp, typename = decltype(_Tp())>
+      static true_type __test(int);
+
+    template<typename>
+      static false_type __test(...);
+  };
+
+  template<typename _Tp>
+    struct __is_default_constructible_impl
+    : public __do_is_default_constructible_impl
+    {
+      typedef decltype(__test<_Tp>(0)) type;
+    };
+
+  template<typename _Tp>
+    struct __is_default_constructible_atom
+    : public __and_<__not_<is_void<_Tp>>,
+                    __is_default_constructible_impl<_Tp>>::type
+    { };
+
+  template<typename _Tp, bool = is_array<_Tp>::value>
+    struct __is_default_constructible_safe;
+
+  // The following technique is a workaround for a current core language
+  // restriction, which does not allow for array types to occur in 
+  // functional casts of the form T().  Complete arrays can be default-
+  // constructed, if the element type is default-constructible, but 
+  // arrays with unknown bounds are not.
+  template<typename _Tp>
+    struct __is_default_constructible_safe<_Tp, true>
+    : public __and_<__is_array_known_bounds<_Tp>,
+		    __is_default_constructible_atom<typename
+                      remove_all_extents<_Tp>::type>>::type
+    { };
+
+  template<typename _Tp>
+    struct __is_default_constructible_safe<_Tp, false>
+    : public __is_default_constructible_atom<_Tp>::type
+    { };
+
+  /// is_default_constructible
+  template<typename _Tp>
+    struct is_default_constructible
+    : public integral_constant<bool, (__is_default_constructible_safe<
+				      _Tp>::value)>
+    { };
+
+
+  // Implementation of is_constructible.
+
+  // The hardest part of this trait is the binary direct-initialization
+  // case, because we hit into a functional cast of the form T(arg).
+  // This implementation uses different strategies depending on the
+  // target type to reduce the test overhead as much as possible:
+  //
+  // a) For a reference target type, we use a static_cast expression 
+  //    modulo its extra cases.
+  //
+  // b) For a non-reference target type we use a ::new expression.
+  struct __do_is_static_castable_impl
+  {
+    template<typename _From, typename _To, typename
+             = decltype(static_cast<_To>(declval<_From>()))>
+      static true_type __test(int);
+
+    template<typename, typename>
+      static false_type __test(...);
+  };
+
+  template<typename _From, typename _To>
+    struct __is_static_castable_impl
+    : public __do_is_static_castable_impl
+    {
+      typedef decltype(__test<_From, _To>(0)) type;
+    };
+
+  template<typename _From, typename _To>
+    struct __is_static_castable_safe
+    : public __is_static_castable_impl<_From, _To>::type
+    { };
+
+  // __is_static_castable
+  template<typename _From, typename _To>
+    struct __is_static_castable
+    : public integral_constant<bool, (__is_static_castable_safe<
+				      _From, _To>::value)>
+    { };
+
+  // Implementation for non-reference types. To meet the proper
+  // variable definition semantics, we also need to test for
+  // is_destructible in this case.
+  struct __do_is_direct_constructible_impl
+  {
+    template<typename _Tp, typename _Arg, typename
+	     = decltype(::new _Tp(declval<_Arg>()))>
+      static true_type __test(int);
+
+    template<typename, typename>
+      static false_type __test(...);
+  };
+
+  template<typename _Tp, typename _Arg>
+    struct __is_direct_constructible_impl
+    : public __do_is_direct_constructible_impl
+    {
+      typedef decltype(__test<_Tp, _Arg>(0)) type;
+    };
+
+  template<typename _Tp, typename _Arg>
+    struct __is_direct_constructible_new_safe
+    : public __and_<is_destructible<_Tp>,
+                    __is_direct_constructible_impl<_Tp, _Arg>>::type
+    { };
+
+  template<typename, typename>
+    struct is_same;
+
+  template<typename, typename>
+    struct is_base_of;
+
+  template<typename>
+    struct remove_reference;
+
+  template<typename _From, typename _To, bool
+           = is_reference<_From>::value>
+    struct __is_base_to_derived_ref;
+
+  template<typename _From, typename _To>
+    struct __is_base_to_derived_ref<_From, _To, true>
+    {
+      typedef typename remove_cv<typename remove_reference<_From
+        >::type>::type __src_t;
+      typedef typename remove_cv<typename remove_reference<_To
+        >::type>::type __dst_t;
+      typedef __and_<__not_<is_same<__src_t, __dst_t>>,
+		     is_base_of<__src_t, __dst_t>> type;
+      static constexpr bool value = type::value;
+    };
+
+  template<typename _From, typename _To>
+    struct __is_base_to_derived_ref<_From, _To, false>
+    : public false_type
+    { };
+
+  template<typename _From, typename _To, bool
+           = __and_<is_lvalue_reference<_From>,
+                    is_rvalue_reference<_To>>::value>
+    struct __is_lvalue_to_rvalue_ref;
+
+  template<typename _From, typename _To>
+    struct __is_lvalue_to_rvalue_ref<_From, _To, true>
+    {
+      typedef typename remove_cv<typename remove_reference<
+        _From>::type>::type __src_t;
+      typedef typename remove_cv<typename remove_reference<
+        _To>::type>::type __dst_t;
+      typedef __or_<is_same<__src_t, __dst_t>,
+		    is_base_of<__dst_t, __src_t>> type;
+      static constexpr bool value = type::value;
+    };
+
+  template<typename _From, typename _To>
+    struct __is_lvalue_to_rvalue_ref<_From, _To, false>
+    : public false_type
+    { };
+
+  // Here we handle direct-initialization to a reference type as 
+  // equivalent to a static_cast modulo overshooting conversions.
+  // These are restricted to the following conversions:
+  //    a) A glvalue of a base class to a derived class reference
+  //    b) An lvalue to an rvalue-reference of reference-compatible 
+  //       types
+  template<typename _Tp, typename _Arg>
+    struct __is_direct_constructible_ref_cast
+    : public __and_<__is_static_castable<_Arg, _Tp>,
+                    __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>,
+                                 __is_lvalue_to_rvalue_ref<_Arg, _Tp>
+                   >>>::type
+    { };
+
+  template<typename _Tp, typename _Arg>
+    struct __is_direct_constructible_new
+    : public conditional<is_reference<_Tp>::value,
+			 __is_direct_constructible_ref_cast<_Tp, _Arg>,
+			 __is_direct_constructible_new_safe<_Tp, _Arg>
+			 >::type
+    { };
+
+  template<typename _Tp, typename _Arg>
+    struct __is_direct_constructible
+    : public integral_constant<bool, (__is_direct_constructible_new<
+				      _Tp, _Arg>::value)>
+    { };
+
+  // Since default-construction and binary direct-initialization have
+  // been handled separately, the implementation of the remaining
+  // n-ary construction cases is rather straightforward.
+  struct __do_is_nary_constructible_impl
+  {
+    template<typename _Tp, typename... _Args, typename
+             = decltype(_Tp(declval<_Args>()...))>
+      static true_type __test(int);
+
+    template<typename, typename...>
+      static false_type __test(...);
+  };
+
+  template<typename _Tp, typename... _Args>
+    struct __is_nary_constructible_impl
+    : public __do_is_nary_constructible_impl
+    {
+      typedef decltype(__test<_Tp, _Args...>(0)) type;
+    };
+
+  template<typename _Tp, typename... _Args>
+    struct __is_nary_constructible
+    : public __is_nary_constructible_impl<_Tp, _Args...>::type
+    {
+      static_assert(sizeof...(_Args) > 1,
+                    "Only useful for > 1 arguments");
+    };
+
+  template<typename _Tp, typename... _Args>
+    struct __is_constructible_impl
+    : public __is_nary_constructible<_Tp, _Args...>
+    { };
+
+  template<typename _Tp, typename _Arg>
+    struct __is_constructible_impl<_Tp, _Arg>
+    : public __is_direct_constructible<_Tp, _Arg>
+    { };
+
+  template<typename _Tp>
+    struct __is_constructible_impl<_Tp>
+    : public is_default_constructible<_Tp>
+    { };
+
+  /// is_constructible
+  template<typename _Tp, typename... _Args>
+    struct is_constructible
+    : public integral_constant<bool, (__is_constructible_impl<_Tp,
+				      _Args...>::value)>
+    { };
+
+  template<typename _Tp, bool = is_void<_Tp>::value>
+    struct __is_copy_constructible_impl;
+
+  template<typename _Tp>
+    struct __is_copy_constructible_impl<_Tp, true>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_copy_constructible_impl<_Tp, false>
+    : public is_constructible<_Tp, const _Tp&>
+    { };
+
+  /// is_copy_constructible
+  template<typename _Tp>
+    struct is_copy_constructible
+    : public __is_copy_constructible_impl<_Tp>
+    { };
+
+  template<typename _Tp, bool = is_void<_Tp>::value>
+    struct __is_move_constructible_impl;
+
+  template<typename _Tp>
+    struct __is_move_constructible_impl<_Tp, true>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_move_constructible_impl<_Tp, false>
+    : public is_constructible<_Tp, _Tp&&>
+    { };
+
+  /// is_move_constructible
+  template<typename _Tp>
+    struct is_move_constructible
+    : public __is_move_constructible_impl<_Tp>
+    { };
+
+  template<typename _Tp>
+    struct __is_nt_default_constructible_atom
+    : public integral_constant<bool, noexcept(_Tp())>
+    { };
+
+  template<typename _Tp, bool = is_array<_Tp>::value>
+    struct __is_nt_default_constructible_impl;
+
+  template<typename _Tp>
+    struct __is_nt_default_constructible_impl<_Tp, true>
+    : public __and_<__is_array_known_bounds<_Tp>,
+		    __is_nt_default_constructible_atom<typename
+                      remove_all_extents<_Tp>::type>>::type
+    { };
+
+  template<typename _Tp>
+    struct __is_nt_default_constructible_impl<_Tp, false>
+    : public __is_nt_default_constructible_atom<_Tp>
+    { };
+
+  /// is_nothrow_default_constructible
+  template<typename _Tp>
+    struct is_nothrow_default_constructible
+    : public __and_<is_default_constructible<_Tp>,
+                    __is_nt_default_constructible_impl<_Tp>>::type
+    { };
+
+  template<typename _Tp, typename... _Args>
+    struct __is_nt_constructible_impl
+    : public integral_constant<bool, noexcept(_Tp(declval<_Args>()...))>
+    { };
+
+  template<typename _Tp, typename _Arg>
+    struct __is_nt_constructible_impl<_Tp, _Arg>
+    : public integral_constant<bool,
+                               noexcept(static_cast<_Tp>(declval<_Arg>()))>
+    { };
+
+  template<typename _Tp>
+    struct __is_nt_constructible_impl<_Tp>
+    : public is_nothrow_default_constructible<_Tp>
+    { };
+
+  /// is_nothrow_constructible
+  template<typename _Tp, typename... _Args>
+    struct is_nothrow_constructible
+    : public __and_<is_constructible<_Tp, _Args...>,
+		    __is_nt_constructible_impl<_Tp, _Args...>>::type
+    { };
+
+  template<typename _Tp, bool = is_void<_Tp>::value>
+    struct __is_nothrow_copy_constructible_impl;
+
+  template<typename _Tp>
+    struct __is_nothrow_copy_constructible_impl<_Tp, true>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_nothrow_copy_constructible_impl<_Tp, false>
+    : public is_nothrow_constructible<_Tp, const _Tp&>
+    { };
+
+  /// is_nothrow_copy_constructible
+  template<typename _Tp>
+    struct is_nothrow_copy_constructible
+    : public __is_nothrow_copy_constructible_impl<_Tp>
+    { };
+
+  template<typename _Tp, bool = is_void<_Tp>::value>
+    struct __is_nothrow_move_constructible_impl;
+
+  template<typename _Tp>
+    struct __is_nothrow_move_constructible_impl<_Tp, true>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_nothrow_move_constructible_impl<_Tp, false>
+    : public is_nothrow_constructible<_Tp, _Tp&&>
+    { };
+
+  /// is_nothrow_move_constructible
+  template<typename _Tp>
+    struct is_nothrow_move_constructible
+    : public __is_nothrow_move_constructible_impl<_Tp>
+    { };
+
+  template<typename _Tp, typename _Up>
+    class __is_assignable_helper
+    : public __sfinae_types
+    {
+      template<typename _Tp1, typename _Up1>
+        static decltype(declval<_Tp1>() = declval<_Up1>(), __one())
+	__test(int);
+
+      template<typename, typename>
+        static __two __test(...);
+
+    public:
+      static constexpr bool value = sizeof(__test<_Tp, _Up>(0)) == 1;
+    };
+
+  /// is_assignable
+  template<typename _Tp, typename _Up>
+    struct is_assignable
+    : public integral_constant<bool,
+                               __is_assignable_helper<_Tp, _Up>::value>
+    { };
+
+  template<typename _Tp, bool = is_void<_Tp>::value>
+    struct __is_copy_assignable_impl;
+
+  template<typename _Tp>
+    struct __is_copy_assignable_impl<_Tp, true>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_copy_assignable_impl<_Tp, false>
+    : public is_assignable<_Tp&, const _Tp&>
+    { };
+
+  /// is_copy_assignable
+  template<typename _Tp>
+    struct is_copy_assignable
+    : public __is_copy_assignable_impl<_Tp>
+    { };
+
+  template<typename _Tp, bool = is_void<_Tp>::value>
+    struct __is_move_assignable_impl;
+
+  template<typename _Tp>
+    struct __is_move_assignable_impl<_Tp, true>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_move_assignable_impl<_Tp, false>
+    : public is_assignable<_Tp&, _Tp&&>
+    { };
+
+  /// is_move_assignable
+  template<typename _Tp>
+    struct is_move_assignable
+    : public __is_move_assignable_impl<_Tp>
+    { };
+
+  template<typename _Tp, typename _Up>
+    struct __is_nt_assignable_impl
+    : public integral_constant<bool, noexcept(declval<_Tp>() = declval<_Up>())>
+    { };
+
+  /// is_nothrow_assignable
+  template<typename _Tp, typename _Up>
+    struct is_nothrow_assignable
+    : public __and_<is_assignable<_Tp, _Up>,
+		    __is_nt_assignable_impl<_Tp, _Up>>::type
+    { };
+
+  template<typename _Tp, bool = is_void<_Tp>::value>
+    struct __is_nt_copy_assignable_impl;
+
+  template<typename _Tp>
+    struct __is_nt_copy_assignable_impl<_Tp, true>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_nt_copy_assignable_impl<_Tp, false>
+    : public is_nothrow_assignable<_Tp&, const _Tp&>
+    { };
+
+  /// is_nothrow_copy_assignable
+  template<typename _Tp>
+    struct is_nothrow_copy_assignable
+    : public __is_nt_copy_assignable_impl<_Tp>
+    { };
+
+  template<typename _Tp, bool = is_void<_Tp>::value>
+    struct __is_nt_move_assignable_impl;
+
+  template<typename _Tp>
+    struct __is_nt_move_assignable_impl<_Tp, true>
+    : public false_type { };
+
+  template<typename _Tp>
+    struct __is_nt_move_assignable_impl<_Tp, false>
+    : public is_nothrow_assignable<_Tp&, _Tp&&>
+    { };
+
+  /// is_nothrow_move_assignable
+  template<typename _Tp>
+    struct is_nothrow_move_assignable
+    : public __is_nt_move_assignable_impl<_Tp>
+    { };
+
+  /// has_trivial_default_constructor
+  template<typename _Tp>
+    struct has_trivial_default_constructor
+    : public integral_constant<bool, __has_trivial_constructor(_Tp)>
+    { };
+
+  /// has_trivial_copy_constructor
+  template<typename _Tp>
+    struct has_trivial_copy_constructor
+    : public integral_constant<bool, __has_trivial_copy(_Tp)>
+    { };
+
+  /// has_trivial_copy_assign
+  template<typename _Tp>
+    struct has_trivial_copy_assign
+    : public integral_constant<bool, __has_trivial_assign(_Tp)>
+    { };
+
+  /// has_trivial_destructor
+  template<typename _Tp>
+    struct has_trivial_destructor
+    : public integral_constant<bool, __has_trivial_destructor(_Tp)>
+    { };
+
+  /// has_virtual_destructor
+  template<typename _Tp>
+    struct has_virtual_destructor
+    : public integral_constant<bool, __has_virtual_destructor(_Tp)>
+    { };
+
+  
+  // type property queries.
+
+  /// alignment_of
+  template<typename _Tp>
+    struct alignment_of
+    : public integral_constant<size_t, __alignof__(_Tp)> { };
+  
+  /// rank
+  template<typename>
+    struct rank
+    : public integral_constant<size_t, 0> { };
+   
+  template<typename _Tp, size_t _Size>
+    struct rank<_Tp[_Size]>
+    : public integral_constant<size_t, 1 + rank<_Tp>::value> { };
+
+  template<typename _Tp>
+    struct rank<_Tp[]>
+    : public integral_constant<size_t, 1 + rank<_Tp>::value> { };
+
+  /// extent
+  template<typename, unsigned _Uint>
+    struct extent
+    : public integral_constant<size_t, 0> { };
+  
+  template<typename _Tp, unsigned _Uint, size_t _Size>
+    struct extent<_Tp[_Size], _Uint>
+    : public integral_constant<size_t,
+			       _Uint == 0 ? _Size : extent<_Tp,
+							   _Uint - 1>::value>
+    { };
+
+  template<typename _Tp, unsigned _Uint>
+    struct extent<_Tp[], _Uint>
+    : public integral_constant<size_t,
+			       _Uint == 0 ? 0 : extent<_Tp,
+						       _Uint - 1>::value>
+    { };
+
+
+  // type relations.
+
+  /// is_same
+  template<typename, typename>
+    struct is_same
+    : public false_type { };
+
+  template<typename _Tp>
+    struct is_same<_Tp, _Tp>
+    : public true_type { };
+
+  /// is_base_of
+  template<typename _Base, typename _Derived>
+    struct is_base_of
+    : public integral_constant<bool, __is_base_of(_Base, _Derived)>
+    { };
+
+  template<typename _From, typename _To,
+           bool = __or_<is_void<_From>, is_function<_To>,
+                        is_array<_To>>::value>
+    struct __is_convertible_helper
+    { static constexpr bool value = is_void<_To>::value; };
+
+  template<typename _From, typename _To>
+    class __is_convertible_helper<_From, _To, false>
+    : public __sfinae_types
+    {
+      template<typename _To1>
+        static void __test_aux(_To1);
+
+      template<typename _From1, typename _To1>
+        static decltype(__test_aux<_To1>(declval<_From1>()), __one())
+	__test(int);
+
+      template<typename, typename>
+        static __two __test(...);
+
+    public:
+      static constexpr bool value = sizeof(__test<_From, _To>(0)) == 1;
+    };
+
+  /// is_convertible
+  template<typename _From, typename _To>
+    struct is_convertible
+    : public integral_constant<bool,
+			       __is_convertible_helper<_From, _To>::value>
+    { };
+
+  /// is_explicitly_convertible
+  template<typename _From, typename _To>
+    struct is_explicitly_convertible
+    : public is_constructible<_To, _From>
+    { };
+
+
+  // const-volatile modifications.
+
+  /// remove_const
+  template<typename _Tp>
+    struct remove_const
+    { typedef _Tp     type; };
+
+  template<typename _Tp>
+    struct remove_const<_Tp const>
+    { typedef _Tp     type; };
+  
+  /// remove_volatile
+  template<typename _Tp>
+    struct remove_volatile
+    { typedef _Tp     type; };
+
+  template<typename _Tp>
+    struct remove_volatile<_Tp volatile>
+    { typedef _Tp     type; };
+  
+  /// remove_cv
+  template<typename _Tp>
+    struct remove_cv
+    {
+      typedef typename
+      remove_const<typename remove_volatile<_Tp>::type>::type     type;
+    };
+  
+  /// add_const
+  template<typename _Tp>
+    struct add_const
+    { typedef _Tp const     type; };
+   
+  /// add_volatile
+  template<typename _Tp>
+    struct add_volatile
+    { typedef _Tp volatile     type; };
+  
+  /// add_cv
+  template<typename _Tp>
+    struct add_cv
+    {
+      typedef typename
+      add_const<typename add_volatile<_Tp>::type>::type     type;
+    };
+
+
+  // Reference transformations.
+
+  /// remove_reference
+  template<typename _Tp>
+    struct remove_reference
+    { typedef _Tp   type; };
+
+  template<typename _Tp>
+    struct remove_reference<_Tp&>
+    { typedef _Tp   type; };
+
+  template<typename _Tp>
+    struct remove_reference<_Tp&&>
+    { typedef _Tp   type; };
+
+  template<typename _Tp,
+	   bool = __and_<__not_<is_reference<_Tp>>,
+                         __not_<is_void<_Tp>>>::value,
+	   bool = is_rvalue_reference<_Tp>::value>
+    struct __add_lvalue_reference_helper
+    { typedef _Tp   type; };
+
+  template<typename _Tp>
+    struct __add_lvalue_reference_helper<_Tp, true, false>
+    { typedef _Tp&   type; };
+
+  template<typename _Tp>
+    struct __add_lvalue_reference_helper<_Tp, false, true>
+    { typedef typename remove_reference<_Tp>::type&   type; };
+
+  /// add_lvalue_reference
+  template<typename _Tp>
+    struct add_lvalue_reference
+    : public __add_lvalue_reference_helper<_Tp>
+    { };
+
+  template<typename _Tp,
+           bool = __and_<__not_<is_reference<_Tp>>,
+                         __not_<is_void<_Tp>>>::value>
+    struct __add_rvalue_reference_helper
+    { typedef _Tp   type; };
+
+  template<typename _Tp>
+    struct __add_rvalue_reference_helper<_Tp, true>
+    { typedef _Tp&&   type; };
+
+  /// add_rvalue_reference
+  template<typename _Tp>
+    struct add_rvalue_reference
+    : public __add_rvalue_reference_helper<_Tp>
+    { };
+
+
+  // sign modifications.
+
+  // Utility for constructing identically cv-qualified types.
+  template<typename _Unqualified, bool _IsConst, bool _IsVol>
+    struct __cv_selector;
+
+  template<typename _Unqualified>
+    struct __cv_selector<_Unqualified, false, false>
+    { typedef _Unqualified __type; };
+
+  template<typename _Unqualified>
+    struct __cv_selector<_Unqualified, false, true>
+    { typedef volatile _Unqualified __type; };
+
+  template<typename _Unqualified>
+    struct __cv_selector<_Unqualified, true, false>
+    { typedef const _Unqualified __type; };
+
+  template<typename _Unqualified>
+    struct __cv_selector<_Unqualified, true, true>
+    { typedef const volatile _Unqualified __type; };
+
+  template<typename _Qualified, typename _Unqualified,
+	   bool _IsConst = is_const<_Qualified>::value,
+	   bool _IsVol = is_volatile<_Qualified>::value>
+    class __match_cv_qualifiers
+    {
+      typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match;
+
+    public:
+      typedef typename __match::__type __type; 
+    };
+
+  // Utility for finding the unsigned versions of signed integral types.
+  template<typename _Tp>
+    struct __make_unsigned
+    { typedef _Tp __type; };
+
+  template<>
+    struct __make_unsigned<char>
+    { typedef unsigned char __type; };
+
+  template<>
+    struct __make_unsigned<signed char>
+    { typedef unsigned char __type; };
+
+  template<>
+    struct __make_unsigned<short>
+    { typedef unsigned short __type; };
+
+  template<>
+    struct __make_unsigned<int>
+    { typedef unsigned int __type; };
+
+  template<>
+    struct __make_unsigned<long>
+    { typedef unsigned long __type; };
+
+  template<>
+    struct __make_unsigned<long long>
+    { typedef unsigned long long __type; };
+
+#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+  template<>
+    struct __make_unsigned<__int128>
+    { typedef unsigned __int128 __type; };
+#endif
+
+  // Select between integral and enum: not possible to be both.
+  template<typename _Tp, 
+	   bool _IsInt = is_integral<_Tp>::value,
+	   bool _IsEnum = is_enum<_Tp>::value>
+    class __make_unsigned_selector;
+
+  template<typename _Tp>
+    class __make_unsigned_selector<_Tp, true, false>
+    {
+      typedef __make_unsigned<typename remove_cv<_Tp>::type> __unsignedt;
+      typedef typename __unsignedt::__type __unsigned_type;
+      typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned;
+
+    public:
+      typedef typename __cv_unsigned::__type __type;
+    };
+
+  template<typename _Tp>
+    class __make_unsigned_selector<_Tp, false, true>
+    {
+      // With -fshort-enums, an enum may be as small as a char.
+      typedef unsigned char __smallest;
+      static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
+      static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned short);
+      static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int);
+      typedef conditional<__b2, unsigned int, unsigned long> __cond2;
+      typedef typename __cond2::type __cond2_type;
+      typedef conditional<__b1, unsigned short, __cond2_type> __cond1;
+      typedef typename __cond1::type __cond1_type;
+
+    public:
+      typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
+    };
+
+  // Given an integral/enum type, return the corresponding unsigned
+  // integer type.
+  // Primary template.
+  /// make_unsigned
+  template<typename _Tp>
+    struct make_unsigned 
+    { typedef typename __make_unsigned_selector<_Tp>::__type type; };
+
+  // Integral, but don't define.
+  template<>
+    struct make_unsigned<bool>;
+
+
+  // Utility for finding the signed versions of unsigned integral types.
+  template<typename _Tp>
+    struct __make_signed
+    { typedef _Tp __type; };
+
+  template<>
+    struct __make_signed<char>
+    { typedef signed char __type; };
+
+  template<>
+    struct __make_signed<unsigned char>
+    { typedef signed char __type; };
+
+  template<>
+    struct __make_signed<unsigned short>
+    { typedef signed short __type; };
+
+  template<>
+    struct __make_signed<unsigned int>
+    { typedef signed int __type; };
+
+  template<>
+    struct __make_signed<unsigned long>
+    { typedef signed long __type; };
+
+  template<>
+    struct __make_signed<unsigned long long>
+    { typedef signed long long __type; };
+
+#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+  template<>
+    struct __make_signed<unsigned __int128>
+    { typedef __int128 __type; };
+#endif
+
+  // Select between integral and enum: not possible to be both.
+  template<typename _Tp, 
+	   bool _IsInt = is_integral<_Tp>::value,
+	   bool _IsEnum = is_enum<_Tp>::value>
+    class __make_signed_selector;
+
+  template<typename _Tp>
+    class __make_signed_selector<_Tp, true, false>
+    {
+      typedef __make_signed<typename remove_cv<_Tp>::type> __signedt;
+      typedef typename __signedt::__type __signed_type;
+      typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed;
+
+    public:
+      typedef typename __cv_signed::__type __type;
+    };
+
+  template<typename _Tp>
+    class __make_signed_selector<_Tp, false, true>
+    {
+      // With -fshort-enums, an enum may be as small as a char.
+      typedef signed char __smallest;
+      static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
+      static const bool __b1 = sizeof(_Tp) <= sizeof(signed short);
+      static const bool __b2 = sizeof(_Tp) <= sizeof(signed int);
+      typedef conditional<__b2, signed int, signed long> __cond2;
+      typedef typename __cond2::type __cond2_type;
+      typedef conditional<__b1, signed short, __cond2_type> __cond1;
+      typedef typename __cond1::type __cond1_type;
+
+    public:
+      typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
+    };
+
+  // Given an integral/enum type, return the corresponding signed
+  // integer type.
+  // Primary template.
+  /// make_signed
+  template<typename _Tp>
+    struct make_signed 
+    { typedef typename __make_signed_selector<_Tp>::__type type; };
+
+  // Integral, but don't define.
+  template<>
+    struct make_signed<bool>;
+
+
+  // array modifications.
+
+  /// remove_extent
+  template<typename _Tp>
+    struct remove_extent
+    { typedef _Tp     type; };
+
+  template<typename _Tp, size_t _Size>
+    struct remove_extent<_Tp[_Size]>
+    { typedef _Tp     type; };
+
+  template<typename _Tp>
+    struct remove_extent<_Tp[]>
+    { typedef _Tp     type; };
+
+  /// remove_all_extents
+  template<typename _Tp>
+    struct remove_all_extents
+    { typedef _Tp     type; };
+
+  template<typename _Tp, size_t _Size>
+    struct remove_all_extents<_Tp[_Size]>
+    { typedef typename remove_all_extents<_Tp>::type     type; };
+
+  template<typename _Tp>
+    struct remove_all_extents<_Tp[]>
+    { typedef typename remove_all_extents<_Tp>::type     type; };
+
+
+  // pointer modifications.
+
+  template<typename _Tp, typename>
+    struct __remove_pointer_helper
+    { typedef _Tp     type; };
+
+  template<typename _Tp, typename _Up>
+    struct __remove_pointer_helper<_Tp, _Up*>
+    { typedef _Up     type; };
+
+  /// remove_pointer
+  template<typename _Tp>
+    struct remove_pointer
+    : public __remove_pointer_helper<_Tp, typename remove_cv<_Tp>::type>
+    { };
+
+  /// add_pointer
+  template<typename _Tp>
+    struct add_pointer
+    { typedef typename remove_reference<_Tp>::type*     type; };
+
+
+  template<size_t _Len>
+    struct __aligned_storage_msa
+    { 
+      union __type
+      {
+	unsigned char __data[_Len];
+	struct __attribute__((__aligned__)) { } __align; 
+      };
+    };
+
+  /**
+   *  @brief Alignment type.
+   *
+   *  The value of _Align is a default-alignment which shall be the
+   *  most stringent alignment requirement for any C++ object type
+   *  whose size is no greater than _Len (3.9). The member typedef
+   *  type shall be a POD type suitable for use as uninitialized
+   *  storage for any object whose size is at most _Len and whose
+   *  alignment is a divisor of _Align.
+  */
+  template<size_t _Len, size_t _Align =
+	   __alignof__(typename __aligned_storage_msa<_Len>::__type)>
+    struct aligned_storage
+    { 
+      union type
+      {
+	unsigned char __data[_Len];
+	struct __attribute__((__aligned__((_Align)))) { } __align; 
+      };
+    };
+
+
+  // Decay trait for arrays and functions, used for perfect forwarding
+  // in make_pair, make_tuple, etc.
+  template<typename _Up, 
+	   bool _IsArray = is_array<_Up>::value,
+	   bool _IsFunction = is_function<_Up>::value> 
+    struct __decay_selector;
+
+  // NB: DR 705.
+  template<typename _Up> 
+    struct __decay_selector<_Up, false, false>
+    { typedef typename remove_cv<_Up>::type __type; };
+
+  template<typename _Up> 
+    struct __decay_selector<_Up, true, false>
+    { typedef typename remove_extent<_Up>::type* __type; };
+
+  template<typename _Up> 
+    struct __decay_selector<_Up, false, true>
+    { typedef typename add_pointer<_Up>::type __type; };
+
+  /// decay
+  template<typename _Tp> 
+    class decay 
+    { 
+      typedef typename remove_reference<_Tp>::type __remove_type;
+
+    public:
+      typedef typename __decay_selector<__remove_type>::__type type;
+    };
+
+  template<typename _Tp>
+    class reference_wrapper;
+
+  // Helper which adds a reference to a type when given a reference_wrapper
+  template<typename _Tp>
+    struct __strip_reference_wrapper
+    {
+      typedef _Tp __type;
+    };
+
+  template<typename _Tp>
+    struct __strip_reference_wrapper<reference_wrapper<_Tp> >
+    {
+      typedef _Tp& __type;
+    };
+
+  template<typename _Tp>
+    struct __strip_reference_wrapper<const reference_wrapper<_Tp> >
+    {
+      typedef _Tp& __type;
+    };
+
+  template<typename _Tp>
+    struct __decay_and_strip
+    {
+      typedef typename __strip_reference_wrapper<
+	typename decay<_Tp>::type>::__type __type;
+    };
+
+
+  // Define a nested type if some predicate holds.
+  // Primary template.
+  /// enable_if
+  template<bool, typename _Tp = void>
+    struct enable_if 
+    { };
+
+  // Partial specialization for true.
+  template<typename _Tp>
+    struct enable_if<true, _Tp>
+    { typedef _Tp type; };
+
+
+  // A conditional expression, but for types. If true, first, if false, second.
+  // Primary template.
+  /// conditional
+  template<bool _Cond, typename _Iftrue, typename _Iffalse>
+    struct conditional
+    { typedef _Iftrue type; };
+
+  // Partial specialization for false.
+  template<typename _Iftrue, typename _Iffalse>
+    struct conditional<false, _Iftrue, _Iffalse>
+    { typedef _Iffalse type; };
+
+
+  /// common_type
+  template<typename... _Tp>
+    struct common_type;
+
+  template<typename _Tp>
+    struct common_type<_Tp>
+    { typedef _Tp type; };
+
+  template<typename _Tp, typename _Up>
+    struct common_type<_Tp, _Up>
+    { typedef decltype(true ? declval<_Tp>() : declval<_Up>()) type; };
+
+  template<typename _Tp, typename _Up, typename... _Vp>
+    struct common_type<_Tp, _Up, _Vp...>
+    {
+      typedef typename
+        common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type;
+    };
+
+  /// underlying_type
+  template<typename _Tp>
+    struct underlying_type
+    {
+      typedef __underlying_type(_Tp) type;
+    };
+
+  /// declval
+  template<typename _Tp>
+    struct __declval_protector
+    {
+      static const bool __stop = false;
+      static typename add_rvalue_reference<_Tp>::type __delegate();
+    };
+
+  template<typename _Tp>
+    inline typename add_rvalue_reference<_Tp>::type
+    declval() noexcept
+    {
+      static_assert(__declval_protector<_Tp>::__stop,
+		    "declval() must not be used!");
+      return __declval_protector<_Tp>::__delegate();
+    }
+
+  /// result_of
+  template<typename _Signature>
+    class result_of;
+
+  template<typename _MemPtr, typename _Arg>
+    struct _Result_of_memobj;
+
+  template<typename _Res, typename _Class, typename _Arg>
+    struct _Result_of_memobj<_Res _Class::*, _Arg>
+    {
+    private:
+      typedef _Res _Class::* _Func;
+
+      template<typename _Tp>
+	static _Tp _S_get(const _Class&);
+      template<typename _Tp>
+	static decltype(*declval<_Tp>()) _S_get(...);
+        
+    public:
+      typedef
+        decltype(_S_get<_Arg>(declval<_Arg>()).*declval<_Func>())
+        __type;
+    };
+
+  template<typename _MemPtr, typename _Arg, typename... _ArgTypes>
+    struct _Result_of_memfun;
+
+  template<typename _Res, typename _Class, typename _Arg, typename... _Args>
+    struct _Result_of_memfun<_Res _Class::*, _Arg, _Args...>
+    {
+    private:
+      typedef _Res _Class::* _Func;
+
+      template<typename _Tp>
+	static _Tp _S_get(const _Class&);
+      template<typename _Tp>
+	static decltype(*declval<_Tp>()) _S_get(...);
+        
+    public:
+      typedef
+        decltype((_S_get<_Arg>(declval<_Arg>()).*declval<_Func>())
+            (declval<_Args>()...) )
+        __type;
+    };
+
+  template<bool, bool, typename _Functor, typename... _ArgTypes>
+    struct _Result_of_impl;
+
+  template<typename _Functor, typename... _ArgTypes>
+    struct _Result_of_impl<false, false, _Functor, _ArgTypes...>
+    {
+      typedef
+        decltype( declval<_Functor>()(declval<_ArgTypes>()...) )
+        __type;
+    };
+
+  template<typename _MemPtr, typename _Arg>
+    struct _Result_of_impl<true, false, _MemPtr, _Arg>
+    : _Result_of_memobj<typename remove_reference<_MemPtr>::type, _Arg>
+    {
+      typedef typename _Result_of_memobj<
+	typename remove_reference<_MemPtr>::type, _Arg>::__type
+	__type;
+    };
+
+  template<typename _MemPtr, typename _Arg, typename... _ArgTypes>
+    struct _Result_of_impl<false, true, _MemPtr, _Arg, _ArgTypes...>
+    : _Result_of_memfun<typename remove_reference<_MemPtr>::type, _Arg,
+                        _ArgTypes...>
+    {
+      typedef typename _Result_of_memfun<
+	typename remove_reference<_MemPtr>::type, _Arg, _ArgTypes...>::__type
+	__type;
+    };
+
+  template<typename _Functor, typename... _ArgTypes>
+    struct result_of<_Functor(_ArgTypes...)>
+    : _Result_of_impl<is_member_object_pointer<
+                        typename remove_reference<_Functor>::type >::value,
+                      is_member_function_pointer<
+			typename remove_reference<_Functor>::type >::value,
+		      _Functor, _ArgTypes...>
+    {
+      typedef typename _Result_of_impl<
+	is_member_object_pointer<
+	  typename remove_reference<_Functor>::type >::value,
+        is_member_function_pointer<
+	  typename remove_reference<_Functor>::type >::value,
+       	_Functor, _ArgTypes...>::__type
+	type;
+    };
+
+  /**
+   *  Use SFINAE to determine if the type _Tp has a publicly-accessible
+   *  member type _NTYPE.
+   */
+#define _GLIBCXX_HAS_NESTED_TYPE(_NTYPE)                         \
+  template<typename _Tp>                                         \
+    class __has_##_NTYPE##_helper                                \
+    : __sfinae_types                                             \
+    {                                                            \
+      template<typename _Up>                                     \
+        struct _Wrap_type                                        \
+	{ };                                                     \
+                                                                 \
+      template<typename _Up>                                     \
+        static __one __test(_Wrap_type<typename _Up::_NTYPE>*);  \
+                                                                 \
+      template<typename _Up>                                     \
+        static __two __test(...);                                \
+                                                                 \
+    public:                                                      \
+      static constexpr bool value = sizeof(__test<_Tp>(0)) == 1; \
+    };                                                           \
+                                                                 \
+  template<typename _Tp>                                         \
+    struct __has_##_NTYPE                                        \
+    : integral_constant<bool, __has_##_NTYPE##_helper            \
+			<typename remove_cv<_Tp>::type>::value>  \
+    { };
+
+  // @} group metaprogramming
+// _GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+// #endif  // __GXX_EXPERIMENTAL_CXX0X__
+
+#endif  // _GLIBCXX_TYPE_TRAITS