|
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