Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2001-02-20 15:36:18


Daryle Walker wrote on 2/20/01 2:48 PM
>The "char" type is supposed to be like either "signed char" or "unsigned
>char," which one is implementation defined. Similarly, the "wchar_t" type
>is supposed to be like one of the other integral types, which one is
>implementation defined. Could we have some sort of structure indicating
>those types' base types? I guess it would be something like:
>
>//==========================================================================
>template <typename T> struct underlying_type;
>
>template <>
>struct underlying_type<char>
>{
> typedef something base_type;
>};
<snip>
>How would we figure out the types? I guess something using <climits> macros
>and/or comparisons from <limits> values would be used. What header would
>this go under, "type_traits.hpp" or a new one?

I'm sure this could be done with <climits> macros. But the following
might be more fun! :-)

Given a compile-time if:

template <bool b, typename IF, typename ELSE>
struct ct_if
{
        typedef IF type;
};

template <typename IF, typename ELSE>
struct ct_if<false, IF, ELSE>
{
        typedef ELSE type;
};

and is_signed:

template <class T> struct is_signed
        {static const bool value = T(-1) < T(0);};

(both of which I believe boost already has)

And given to_signed and to_unsigned (which I don't think boost currently
has):

template <class T> struct to_unsigned
        {typedef T type;};
template <> struct to_unsigned<char>
        {typedef unsigned char type;};
template <> struct to_unsigned<signed char>
        {typedef unsigned char type;};
template <> struct to_unsigned<short>
        {typedef unsigned short type;};
template <> struct to_unsigned<int>
        {typedef unsigned int type;};
template <> struct to_unsigned<long>
        {typedef unsigned long type;};
#ifdef BOOST_LONGLONG_SUPPORT
        template <> struct to_unsigned<long long>
                {typedef unsigned long long type;};
#endif

template <class T> struct to_signed
        {typedef T type;};
template <> struct to_signed<char>
        {typedef signed char type;};
template <> struct to_signed<unsigned char>
        {typedef signed char type;};
template <> struct to_signed<unsigned short>
        {typedef short type;};
template <> struct to_signed<unsigned int>
        {typedef int type;};
template <> struct to_signed<unsigned long>
        {typedef long type;};
#ifdef BOOST_LONGLONG_SUPPORT
        template <> struct to_signed<unsigned long long>
                {typedef long long type;};
#endif

Then:

template <typename charT> struct underlying_type;

template <>
struct underlying_type<char>
{
public:
        typedef typename ct_if<is_signed<char>::value,
                typename to_signed<char>::type,
                typename to_unsigned<char>::type>::type type;
};

template <>
struct underlying_type<wchar_t>
{
private:
        typedef typename ct_if<sizeof(wchar_t) == sizeof(char),
                char,
                typename ct_if<sizeof(wchar_t) == sizeof(short),
                        short,
                        typename ct_if<sizeof(wchar_t) == sizeof(int),
                                int,
                                long
>::type
>::type
>::type A;
public:
        typedef typename ct_if<is_signed<wchar_t>::value,
                typename to_signed<A>::type,
                typename to_unsigned<A>::type>::type type;
};

Seems like I've seen someone talk about a "integral best fit" lib that
might simplify all the if'ing I'm doing in the wchar_t specialization,
but alas I can't remember who or where.

After all that, this is not a comment on your first question of whether
such a struct should be part of boost. It is simply a sample
implementation.

-Howard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk