[v3] ext/type_traits.h
Martin Sebor
sebor@roguewave.com
Thu Sep 28 16:04:00 GMT 2006
Sorry to jump in on this discussion with only a tangentially
related question, but I'm wondering if this functionality is
being proposed for C++ (or if there are plans to do so).
Btw., we've also had the need for signed/unsigned conversion in
our library in the past. We dealt with it by adding a typedef or
two to numeric_limits, something like this (we don't have them
anymore but at one point private versions of them were in there):
numeric_limits<T>::signed_type
numeric_limits<T>::unsigned_type
Martin
Howard Hinnant wrote:
> On Sep 28, 2006, at 10:14 AM, Benjamin Kosnik wrote:
>
>>
>>> In the use cases I've personally been involved with, I had an
>>> integral type T which could be either signed or unsigned, and I
>>> needed to get its unsigned counterpart (or signed counterpart).
>>> Actually the former (unsigned counterpart) was my more common need.
>>> Having to spell that typename __add_unsigned<typename
>>> __remove_signed<T>::type>::type seems cumbersome.
>>
>>
>> All this seems unduly complicated to me.
>>
>> TR1 already has traits for is_signed or is_unsigned. Together with
>> __conditional_type (hopefully spelled conditional_type in TR2 or
>> wherever) gives:
>>
>> // To get unsigned type.
>> conditional_type(is_signed<T>::value, add_unsigned<T>::type, T)
>>
>> This seems reasonable to me, and quite readable.
>>
>> ?
>>
>> C++ doesn't currently have "to" traits or utils. Why add them? If you
>> add this, will "to_const" be next?
>>
>> ;)
>
>
> I just looked at the latest version of __add_unsigned in ext/
> type_traits.h. The above (very reasonable) recipe breaks for signed
> char. I see no way to turn a signed char into an unsigned char. If
> add_unsigned<signed char>::type would deliver an unsigned char instead
> of a signed char, then I think we would be set.
>
> Similarly, both remove_unsigned<unsigned char>::type and
> remove_unsigned<char>::type should probably yield signed char instead
> of char, at least when char is unsigned. I'd hate to say
> remove_unsigned<char>::type and get an unsigned type.
>
> I think the basic conflict here is: Do these traits reflect syntax or
> semantics? I'm urging the latter (and don't have strong feelings on
> what we call it).
>
> With those changes, we don't even need your suggested recipe using
> conditional_type:
>
> // To get unsigned type.
> add_unsigned<T>::type
>
> The condition is built into add_unsigned.
>
> As it stands today, we would need:
>
> // To get unsigned type.
> conditional_type(is_same<T, signed char>::value, unsigned char,
> add_unsigned<T>::type)
>
> One final nit: add_unsigned<const short>::type yields what? I
> recommend const unsigned short.
>
> namespace detail
> {
>
> template <class T, bool make_const, bool make_volatile>
> struct union_cv;
>
> template <class T>
> struct union_cv<T, false, false>
> {
> typedef T type;
> };
>
> template <class T>
> struct union_cv<T, false, true>
> {
> typedef volatile T type;
> };
>
> template <class T>
> struct union_cv<T, true, false>
> {
> typedef const T type;
> };
>
> template <class T>
> struct union_cv<T, true, true>
> {
> typedef const volatile T type;
> };
>
> }
>
> template <class T, class U>
> struct union_cv
> {
> typedef typename std::tr1::remove_cv<T>::type Tr;
> typedef typename std::tr1::remove_cv<U>::type Ur;
> static const bool make_const = std::tr1::is_const<T>::value ||
> std::tr1::is_const<U>::value;
> static const bool make_volatile = std::tr1::is_volatile<T>::value
> || std::tr1::is_volatile<U>::value;
> typedef typename detail::union_cv<Tr, make_const,
> make_volatile>::type type;
> };
>
> namespace detail
> {
> template<typename _Value>
> struct add_unsigned
> { typedef _Value type; };
>
> template<>
> struct add_unsigned<char>
> { typedef unsigned char type; };
>
> template<>
> struct add_unsigned<signed char>
> { typedef unsigned char type; };
>
> template<>
> struct add_unsigned<short>
> { typedef unsigned short type; };
>
> template<>
> struct add_unsigned<int>
> { typedef unsigned int type; };
>
> template<>
> struct add_unsigned<long>
> { typedef unsigned long type; };
>
> template<>
> struct add_unsigned<long long>
> { typedef unsigned long long type; };
> }
>
> template <class T>
> struct add_unsigned
> {
> typedef typename union_cv<typename detail::add_unsigned<typename
> std::tr1::remove_cv<T>::type>::type, T>::type type;
> };
>
> union_cv probably needs a better name, but I've found it useful more
> than once.
>
> -Howard
>
More information about the Libstdc++
mailing list