Re: [boost] Traits for character underlying types
by Howard Hinnant other posts by this author
Feb 20 2001 8:36PM messages near this date
RE: [boost] Where's this convenient macro? (was: Re: type_traits again)
|
Where's this convenient macro? (was: Re: type_traits again)
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
|