Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2000-10-19 16:01:07


Herve Bronnimann wrote on 10/19/2000 4:00 PM
>Upon designing generic compression filters, I stumbled onto the problem
>of retrieving the unsigned numeric type corresponding to a given
>integral or character type. The problem is to map a symbol onto an index
>into an array, suitably so that indices range in [0,max_index+1).
>Thus the concept of a symbol map.
>
>Apparently, char_traits gives a conversion to an integral type, but this
>integral might be signed. To convert to the corresponding unsigned
>type, using the same or more bits, I wrote the following class template.
>
>It's not clear to me if <boost/integer.hpp> and <boost/type_traits.hpp>
>can shorten my code. In particular, neither of them would let me handle
>wchar_t. It would be possible however to use them to avoid unnecessary
>conversions. In this particular case, I couldn't find how to solve my
>problem using only the boost libraries.
>
>As I am a beginner to boost, please bear with me and let me know if my
>emails are off-topic for this list. Especially about mailing code which
>is not in boost (yet?). Any comments appreciated,

Interesting problem. It would be nice to implement this without having
to re-list all of the built-in types.

Imagine a helper struct named remove_signedness, that would map an
unsigned type to itself, and a signed type to its unsigned counterpart.
Given this reuseable utility, I believe your special_symbol_map could be
simplified:

template <class Symbol>
struct special_symbol_map
{
        typedef Symbol symbol_type;
        typedef typename remove_signedness<Symbol>::type index_type;
        // ...
};

remove_signedness is going to depend upon being able to test if a
(presumable arithmetic) type is signed or not. is_signed should probably
have been included in type_traits.hpp but was not*. It could look like:

// is_signed/unsigned

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

template <class T> struct is_unsigned
        {static const bool value = !is_signed<T>::value;};

(*Footnote: this utility does appear in the Metrowerks version of
type_traits <msl_utility>)

Given is_signed and integer.hpp, remove_signedness might look like:

namespace details
{

        template <class T, bool is_signed>
        struct remove_signedness_helper
        {
                typedef T type;
        };

        template <class T>
        struct remove_signedness_helper<T, true>
        {
                typedef typename uint_t<sizeof(T)*CHAR_BIT>::least type;
        };

}

template <class T>
struct remove_signedness
{
        typedef typename details::remove_signedness_helper<T,
is_signed<T>::value>::type type;
};

On my system this works, even for wchar_t (which is unsigned and thus
maps to itself). It also works if char turns out to be unsigned (your
current implementation assumes char is signed, which may not be true).

Hope this helps.

-Howard


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