This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
c++0x vs. tr1 type_traits, round 1
- From: Benjamin Kosnik <bkoz at redhat dot com>
- To: libstdc++ at gcc dot gnu dot org
- Date: Thu, 26 Apr 2007 00:36:15 +0200
- Subject: c++0x vs. tr1 type_traits, round 1
Hey!
Here are some of the type_traits additions voted in during the Oxford
meeting. The __cv_selector bits are based on the post of Howard's when
we were discussing what to do with these traits in August 2006.
The bigger part will probably be to go through and do the changes in
behavior between C++0x and TR1. And, no testing.
Why is there no testing? Well, I realized that there are other, more
important issues to be tackled first.
Issue 1: C++0x type traits and TR1 type traits are incompatible.
ie, is_signed<float> gives different behavior depending on which version
of traits used. I've not gone through and made a detailed list. Now,
don't get me wrong, I'm down with the C++0x change to make <type_traits>
is_signed match <limits> numeric_limits<T>::is_signed.
However, it raises the question: what to do? Should TR1 and C++0x be
mixed at all?
I'm starting to think this is a better course of action:
1) -std=*03 flags, tr1 works as it does now, mangled as std::tr1. C++0x
includes error.
2) -std=*0x flags, tr1 is an alias to std::__cxx200x, ie "updated TR1".
This will still give us partial reuse, and IMHO much saner (consistent)
mix-n-match behavior.
Thoughts? I'm operating under the assumption that Howard's paper N2255
is not a TR1 defect report, per se.
Issue 2: TR1 type traits testing
Wow. We weren't set up to do divergent TR1/C++0x testing. So, I'd like
to go through and set up the testsuite for this. In the process, I'd
like to go through and do the layout changes for tr1/4_metaprogramming
that I did for the rest of the library when C++0x API testing when in,
including instantiation tests, etc etc yadda yadda yadda. Probably
flatten down this stuff to just the traits and not the organizing
subsection, since that stuff is changing and hopefully we can re-use
some of that stuff....
(I skipped <type_traits> and function, and now it's coming back to bite me!)
Thoughts?
Hmmm.
best,
benjamin
2007-04-26 benjamin kosnik <bkoz@montsouris.artheist.org>
* include/std/type_traits (enable_if): New.
(conditional): New.
(__decay_selector, decay): New.
(__cv_selector, __match_cv_qualifiers): New.
(__make_unsigned, __make_unsigned_selector, make_unsigned): New.
(__make_signed, __make_signed_selector, make_signed): New.
(has_trivial_default, has_nothrow_default): New.
Define _GLIBCXX_SUPPRESS_TR1 when including tr1/type_traits.
* include/tr1/type_traits: Move traits incompatible with C++0x
into _GLIBCXX_SUPPRESS_TR1 block.
* testsuite/20_util/headers/type_traits/types_std_c++0x_neg.cc: Mod.
* testsuite/20_util/headers/type_traits/types_std_c++0x.cc: Mod.
Index: include/tr1/type_traits
===================================================================
--- include/tr1/type_traits (revision 124165)
+++ include/tr1/type_traits (working copy)
@@ -270,10 +270,6 @@
{ };
template<typename _Tp>
- struct has_trivial_constructor
- : public integral_constant<bool, is_pod<_Tp>::value> { };
-
- template<typename _Tp>
struct has_trivial_copy
: public integral_constant<bool, is_pod<_Tp>::value> { };
@@ -286,10 +282,6 @@
: public integral_constant<bool, is_pod<_Tp>::value> { };
template<typename _Tp>
- struct has_nothrow_constructor
- : public integral_constant<bool, is_pod<_Tp>::value> { };
-
- template<typename _Tp>
struct has_nothrow_copy
: public integral_constant<bool, is_pod<_Tp>::value> { };
@@ -478,8 +470,7 @@
{ typedef _Tp type; };
// NB: Careful with reference to void.
- template<typename _Tp, bool = (is_void<_Tp>::value
- || is_reference<_Tp>::value)>
+ template<typename _Tp, bool = is_void<_Tp>::value || is_reference<_Tp>::value>
struct __add_reference_helper
{ typedef _Tp& type; };
@@ -614,3 +605,24 @@
}
#endif
+
+// XXX multiple tr1 includes must work
+// tr1 /C++0x must work
+// tr1 in one header shouldn't leak into another
+#if !defined(_GLIBCXX_SUPPRESS_TR1) && !defined(_GLIBCXX_TR1_ONLY_TYPE_TRAITS)
+#define _GLIBCXX_TR1_ONLY_TYPE_TRAITS 1
+// namespace std::tr1
+namespace std
+{
+ namespace tr1
+ {
+ template<typename _Tp>
+ struct has_trivial_constructor
+ : public integral_constant<bool, is_pod<_Tp>::value> { };
+
+ template<typename _Tp>
+ struct has_nothrow_constructor
+ : public integral_constant<bool, is_pod<_Tp>::value> { };
+ } // namespace tr1
+} // namespace std
+#endif
Index: include/std/type_traits
===================================================================
--- include/std/type_traits (revision 124165)
+++ include/std/type_traits (working copy)
@@ -37,10 +37,284 @@
#pragma GCC system_header
#ifdef __GXX_EXPERIMENTAL_CXX0X__
+# define _GLIBCXX_SUPPRESS_TR1
# include <tr1/type_traits>
+# undef _GLIBCXX_SUPPRESS_TR1
#else
# include <c++0x_warning.h>
#endif
+_GLIBCXX_BEGIN_NAMESPACE(std)
+
+ // Define a nested type if some predicate holds.
+ template<bool, typename _Tp = void>
+ struct enable_if
+ { };
+
+ template<typename _Tp>
+ struct enable_if<true, _Tp>
+ { typedef _Tp type; };
+
+
+ // Like a conditional expression, but for types. If true, first, if
+ // false, second.
+ template<bool _Cond, typename _Iftrue, typename _Iffalse>
+ struct conditional
+ { typedef _Iftrue type; };
+
+ template<typename _Iftrue, typename _Iffalse>
+ struct conditional<false, _Iftrue, _Iffalse>
+ { typedef _Iffalse type; };
+
+
+ // Decay trait for arrays and functions, used for perfect forwarding
+ // in make_pair, make_tuple, etc.
+ template<typename _Up,
+ bool = is_array<_Up>::value || is_function<_Up>::value>
+ struct __decay_selector;
+
+ template<typename _Up>
+ struct __decay_selector<_Up, false>
+ { typedef _Up __type; };
+
+ template<typename _Up>
+ struct __decay_selector<_Up, true>
+ {
+ private:
+ static const bool __b = is_array<_Up>::value;
+ typedef typename remove_extent<_Up>::type* __array_type;
+ typedef typename add_pointer<_Up>::type __function_type;
+ typedef conditional<__b, __array_type, __function_type> __cond;
+
+ public:
+ typedef typename __cond::__type __type;
+ };
+
+ template<typename _Tp>
+ struct decay : public __decay_selector<typename remove_reference<_Tp>::type>
+ {
+ private:
+ typedef typename remove_reference<_Tp>::type __remove_type;
+
+ public:
+ typedef typename __decay_selector<__remove_type>::__type type;
+ };
+
+
+ // 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>
+ struct __match_cv_qualifiers
+ {
+ private:
+ typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match;
+ typedef typename __match::__type __type;
+ };
+
+
+ // Utility for finding the unsigned versions of signed integral types.
+ template<typename _Tp>
+ struct __make_unsigned;
+
+ 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; };
+
+
+ // 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>
+ struct __make_unsigned_selector;
+
+ template<typename _Tp>
+ struct __make_unsigned_selector<_Tp, true, false>
+ {
+ private:
+ static const bool __b = is_unsigned<_Tp>::value;
+ typedef __make_unsigned<typename remove_cv<_Tp>::type> __unsignedt;
+ typedef typename __unsignedt::__type __unsigned_type;
+ typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned;
+ typedef typename __cv_unsigned::__type __cv_unsigned_type;
+ typedef conditional<__b, _Tp, __cv_unsigned_type> __cond;
+
+ public:
+ typedef typename __cond::type __type;
+ };
+
+ template<typename _Tp>
+ struct __make_unsigned_selector<_Tp, false, true>
+ {
+ private:
+ // GNU enums start with sizeof int.
+ static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned int);
+ static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned long);
+ typedef conditional<__b2, unsigned long, unsigned long long> __cond;
+ typedef typename __cond::type __cond_type;
+ typedef unsigned int __ui_type;
+
+ public:
+ typedef typename conditional<__b1, __ui_type, __cond_type>::type __type;
+ };
+
+
+ // Primary class template.
+ // Given an integral/enum type, return the corresponding unsigned
+ // integer type.
+ // XXX test char/unsigned char/wchar_t unsigned wchar_t, bool, const
+ // int vs const unsigned int
+ template<typename _Tp>
+ struct make_unsigned
+ { typedef typename __make_unsigned_selector<_Tp>::__type type; };
+
+ // Integral, but don't define.
+ template<>
+ struct make_unsigned<bool>;
+
+ // Integral, but not signed/unsigned.
+ template<>
+ struct make_unsigned<wchar_t>
+ {
+ typedef unsigned wchar_t type;
+ };
+
+
+ // Utility for finding the signed versions of unsigned integral types.
+ template<typename _Tp>
+ struct __make_signed;
+
+ 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; };
+
+
+ // 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>
+ struct __make_signed_selector;
+
+ template<typename _Tp>
+ struct __make_signed_selector<_Tp, true, false>
+ {
+ private:
+ static const bool __b = is_signed<_Tp>::value;
+ typedef __make_signed<typename remove_cv<_Tp>::type> __signedt;
+ typedef typename __signedt::__type __signed_type;
+ typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed;
+ typedef typename __cv_signed::__type __cv_signed_type;
+ typedef conditional<__b, _Tp, __cv_signed_type> __cond;
+
+ public:
+ typedef typename __cond::type __type;
+ };
+
+ template<typename _Tp>
+ struct __make_signed_selector<_Tp, false, true>
+ {
+ private:
+ // GNU enums start with sizeof int.
+ static const bool __b1 = sizeof(_Tp) <= sizeof(signed int);
+ static const bool __b2 = sizeof(_Tp) <= sizeof(signed long);
+ typedef conditional<__b2, signed long, signed long long> __cond;
+ typedef typename __cond::type __cond_type;
+ typedef unsigned int __i_type;
+
+ public:
+ typedef typename conditional<__b1, __i_type, __cond_type>::type __type;
+ };
+
+
+ // Primary class template.
+ // Given an integral/enum type, return the corresponding signed
+ // integer type.
+ // XXX test char/signed char/wchar_t signed wchar_t, bool, const
+ // int vs const signed int
+ template<typename _Tp>
+ struct make_signed
+ { typedef typename __make_signed_selector<_Tp>::__type type; };
+
+ // Integral, but don't define.
+ template<>
+ struct make_signed<bool>;
+
+ // Integral, but not signed/signed.
+ template<>
+ struct make_signed<wchar_t>
+ {
+ typedef signed wchar_t type;
+ };
+
+
+ template<typename _Tp>
+ struct has_trivial_default
+ : public integral_constant<bool, is_pod<_Tp>::value> { };
+
+ template<typename _Tp>
+ struct has_nothrow_default
+ : public integral_constant<bool, is_pod<_Tp>::value> { };
+
+_GLIBCXX_END_NAMESPACE
+
#endif
Index: testsuite/20_util/headers/type_traits/types_std_c++0x.cc
===================================================================
--- testsuite/20_util/headers/type_traits/types_std_c++0x.cc (revision 124165)
+++ testsuite/20_util/headers/type_traits/types_std_c++0x.cc (working copy)
@@ -25,4 +25,14 @@
{
using std::true_type;
using std::false_type;
+
+ // C++0x additions.
+ // XXX should instantiate to see if defined in correct namespace.
+ typedef int test_type;
+ typedef std::decay<test_type> decay_type;
+ typedef std::make_unsigned<test_type> unsigned_type;
+ typedef std::make_signed<test_type> signed_type;
+ typedef std::enable_if<true, test_type> enable_if_type;
+ typedef std::conditional<true, test_type, test_type> conditional_type;
+
}
Index: testsuite/20_util/headers/type_traits/types_std_c++0x_neg.cc
===================================================================
--- testsuite/20_util/headers/type_traits/types_std_c++0x_neg.cc (revision 0)
+++ testsuite/20_util/headers/type_traits/types_std_c++0x_neg.cc (revision 0)
@@ -0,0 +1,33 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2007 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 2, 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.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+#include <type_traits>
+
+namespace gnu
+{
+ // C++0x changes from TR1.
+ typedef int test_type;
+ typedef std::has_trivial_constructor<test_type> trivial_type;
+ typedef std::has_nothrow_constructor<test_type> nothrow_type;
+}
+
+// { dg-error "no" "" { target *-*-* } 28 }
+// { dg-error "no" "" { target *-*-* } 29 }