This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [v3] ext/type_traits.h


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]