|
Boost : |
From: Jeffrey C. Jacobs (darklord_at_[hidden])
Date: 2004-06-28 12:25:07
A while ago I proposed adding a signed_traits class and then after
receiving some input decided it better this be a property of some
existing traits object, ideally "integer_traits" since only integer can
be signed.
I tried to contact some people to whom I'd been referred about changing
integer_traits.hpp but never heard back. Otherwise I have received no
negative feedback from this proposal.
The idea is simple, as with the min and max constants associated with
boost::integer_traits, there would be:
boost::integer_traits<x>::unsigned_type
boost::integer_traits<x>::signed_type
I also proposed a
boost::integer_traits<x>::type
But that would be x and so wouldn't be very useful.
With these additions, one would be able to get the signed or unsigned
form of a type without knowing the type detail. In other words, one can
apply "signed" or "unsigned" to any specialized integral type that
supports it. (Obviously bool would not be supported, nor would any
non-integral types.) OTOH, a user-defined pseudo-integral type could
provide its own specialization which would be a way of converting
between signed and unsigned Abstract Integral Types (AITs) in a generic
way:
template <>
class integer_traits<my_signed_type>
: public std::numeric_limits<my_signed_type>,
public detail::signed_integer_traits_base<my_signed_type,
my_unsigned_type>
{
BOOST_STATIC_CONSTANT(bool, is_integral = true);
};
Note: here I do not use the boost::detail::integer_traits_base helper
because my_signed_type does not have a min or max value and even if it
did, it is not possible to do in-class initialization with abstract data
types. I would also be providing a specialization of
std::numeric_limits. Note also because of these orthagonal properties,
I provide a separate base class for signed_integer_traits_base, rather
than adding to integer_traits_base.
The idea would then be to have a new type in the boost::details
namespace:
template <class ST, class UT>
class signed_integer_traits_base
{
public:
typedef ST signed_type;
typedef UT unsigned_type;
};
And define each integral type correspondingly, e.g.:
template<>
class integer_traits<bool>
: public std::numeric_limits<bool>,
public detail::integer_traits_base<bool, false, true>,
public detail::signed_integer_traits_base<bool, bool>
{ };
template<>
class integer_traits<char>
: public std::numeric_limits<char>,
public detail::integer_traits_base<char, CHAR_MIN, CHAR_MAX>,
public detail::signed_integer_traits_base<signed char, unsigned
char>
{ };
// ...
template<>
class integer_traits<int>
: public std::numeric_limits<int>,
public detail::integer_traits_base<int, INT_MIN, INT_MAX>,
public detail::signed_integer_traits_base<signed int, unsigned int>
{ };
template<>
class integer_traits<unsigned int>
: public std::numeric_limits<unsigned int>,
public detail::integer_traits_base<unsigned int, 0, UINT_MAX>,
public detail::signed_integer_traits_base<signed int, unsigned int>
{ };
// ...
The one problem with this as I see is cv-qualification. Clearly, this
will only provide the cv-unqualified types input as if I read ISOC++
14.1.5 correctly, and I may not be, the top-level cv-qualification of
the integral type template parameter would be dropped. E.g.:
boost::integer_traits<const int>::signed_type
would be [signed] int, NOT const [signed] int. In general, this is what
you want because it saves you from writing specialization for each
cv-qualification, but it then looses information about the source type,
namely how it was cv-qualified. For the other traits, where static
functions or constants are provided, the cv-qualification does not
matter; it is only in the manifestation of the typedef that causes this
inconvenience. However, I think this approach better than none though
suggestions and corrections are welcome.
Jeffrey.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk