Proposal: Addition to boost::integer_traits

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.

"Jeffrey C. Jacobs" <darklord@timehorse.com> writes:
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.
Please, no more degenerate traits classes! We need metafunctions instead: unsigned_type<x>::type signed_type<x>::type etc. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

Thanks Dave! I concur, it does seem a better approach because it provides full severability and orthgonality to the other concepts in the subclass of traits. The approach is still to use the metafunction paradigm, but I see your point that having separate types for signed and unsigned would allow for better scaling of concept, keeping each type aspect, signed or unsigned, independent. Thus, I have no problem with something like: template <class X> struct unsigned_type { }; template <class X> struct signed_type { }; // Specializations template <> struct unsigned_type<char> { typedef unsigned char type; }; template <> struct signed_type<char> { typedef signed char type; }; // ... template <> struct unsigned_type<int> { typedef unsigned int type; }; template <> struct signed_type<int> { typedef signed int type; }; template <> struct unsigned_type<unsigned int> { typedef unsigned int type; }; template <> struct signed_type<unsigned int> { typedef signed int type; }; // ... So if that were the format it took, say in its own file, signed.hpp or some such name, would that be more amenable Dave? Further, it seems that given cstdint.hpp and integer.hpp AFAICK I would need specializations for all the types defined there-in. A problem I ignored before then becomes dependencies. Since integer.hpp is defined purely in terms of integeral types, I don't see any problem with one depending on the other since the names in integer.hpp are simply an alias (typedef) for the intrinsics. It is the cstdint.hpp and underlying stdint.h defined in C99 that worries me, since although most implemention will take the 8, 16, 32, 32, 64 approach to char, short, int, long and long long respectively, all that is guarenteed by the standard is at least 8, 16, 16, 32, and 64 for the basic integral types. What can happen therefore is an implementation may choose to define the above integral types as 8, 16, 64, 64, 128, because it wishes to emphasise 64-bit integers as its intrinsic integral type. (It should however use stdint.h to provide an int_fast32_t to be long and make the int a 32-bit value to achieve the desired effect.) This implementation may then provide int32_t (although it does not need to) as an exact typedef for some compiler-specific type __int32, for example. In this case, [un]signed_type will not be specialized for __int32 because it is compiler specific and therefore unsigned_type<int32_t>::type will fail because the type member does not exist in the specializations. OTOH, if such a still ISO C99 conformant compiler did NOT provide an __int32 and therefore an int32_t, as 7.18.1.1.3 clearly states its perogative, cstdint.hpp will fail to compile because int32_t (and uint32_t) does not exist. Therefore, it could be said that signed.hpp would provide a minimal approach to cstdint.hpp in the same way C99 7.18.1.1.3 defines: assume that if the intN_t is not a native size, it will not exist. In a sense, for now I leave it as cstdint.hpp's problem, not signed.hpp. Jeffrey. ----- Original Message ----- From: "David Abrahams" <dave@boost-consulting.com> Newsgroups: gmane.comp.lib.boost.devel Sent: Monday, June 28, 2004 2:07 PM Subject: Re: Proposal: Addition to boost::integer_traits
"Jeffrey C. Jacobs" <darklord@timehorse.com> writes:
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.
Please, no more degenerate traits classes! We need metafunctions instead:
unsigned_type<x>::type signed_type<x>::type
etc.
-- Dave Abrahams Boost Consulting http://www.boost-consulting.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Mon, 28 Jun 2004 13:25:07 -0400, "Jeffrey C. Jacobs" <darklord@timehorse.com> wrote:
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.
As Dave says, integer_traits<> reflects an obsolete approach to traits classes. My opinion is that we should refactor/rewrite most of its stuff. Also I would like it to not depend on numeric_limits. If you begin working at this, here are some small, self-contained, templates that could (well, some of them) fit into the new creature ;) (after making them mpl-compatible metafunctions) http://tinyurl.com/2w97t (the address points directly to a .zip file in the Yahoo! files section - downloading will likely require that you have a Yahoo! account) BTW, I also wrote a new version of static_log2 which has no dependency on numeric_limits and use a better algorithm (suggested, together with a reference implementation, by Vesa Karvonen) than the current one. It will be soon in the CVS. -- Genny.
participants (3)
-
David Abrahams
-
Gennaro Prota
-
Jeffrey C. Jacobs