|
Boost : |
From: Herve Bronnimann (hbr_at_[hidden])
Date: 2000-10-19 15:00:01
Hi everyone:
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,
-- Hervé #ifndef SYMBOL_MAP_H #define SYMBOL_MAP_H /* Symbol maps transform a symbol into an index in an array and vice * versa. Useful for counting frequencies or other encodings without * using maps which are less efficient that arrays. They also * contain the type and size of the return range for builtin types. * You can supply your own symbol_map (if you don't like the default * encoding, you are dealing with another alphabet, for colors in * images, etc.) */ // For signed types, the index_type should be unsigned to avoid trouble // We use partial specialization to override the default for those types // The specializations are at the end of this file for readability template <class Symbol> struct symbol_traits { static const bool is_unsigned = true; typedef Symbol index_type; // the following is a safe expression for 2^n - 1, n <= 8*sizeof(long) static const unsigned long max_index = index_type(-1); }; template <class Symbol> const unsigned long symbol_traits<Symbol>::max_index; // The symbol map takes advantage of the traits template <class Symbol, bool is_unsigned> struct special_symbol_map {}; template <class Symbol> struct symbol_map : special_symbol_map< Symbol, symbol_traits<Symbol>::is_unsigned > {}; // There are two partial specializations. This is because, if unsigned, // the two operator() have the same signature, having them both in // symbol_map:: would result in a conflict. template <class Symbol> struct special_symbol_map<Symbol,true> { typedef Symbol symbol_type; typedef Symbol index_type; index_type operator()(const symbol_type& s) const { return (index_type)s; } // shall I use std::static_cast<>? }; template <class Symbol> struct special_symbol_map<Symbol,false> { typedef Symbol symbol_type; typedef typename symbol_traits<Symbol>::index_type index_type; index_type operator()(const symbol_type& s) const { return (index_type)s; } symbol_type operator()(const index_type& s) const { return (symbol_type)s; } // shall I use std::static_cast<>? }; // Specializations for the symbol_traits #define __declare_index_type(__symbol_type,__signedness,__index_type) \ template <> \ struct symbol_traits<__symbol_type> \ { \ static const bool is_unsigned = __signedness; \ typedef __index_type index_type; \ static const unsigned long max_index = index_type(-1); \ }; \ template <> \ const bool symbol_traits<__symbol_type>::is_unsigned; \ template <> \ const unsigned long symbol_traits<__symbol_type>::max_index; // Integral types as per the standard (3.9.1, p. 53) __declare_index_type(bool,true,bool) __declare_index_type(char,false,unsigned char) __declare_index_type(unsigned char,true,unsigned char) __declare_index_type(signed char,false,unsigned char) __declare_index_type(short,false,unsigned short) __declare_index_type(unsigned short,true,unsigned short) __declare_index_type(int,false,unsigned int) __declare_index_type(unsigned int,true,unsigned int) __declare_index_type(long int,false,unsigned long int) __declare_index_type(unsigned long int,true,unsigned long int) // this type makes it unfortunately not possible to use // <boost/integer.hpp> directly __declare_index_type(wchar_t,false,short) #endif // SYMBOL_MAP_H
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk