[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