Re: [boost] [Review] of binary_int utility starts

Reece Dunn wrote:
Thanks for the suggestion Reece. I thrashed about some this morning turning on extensions. I'm now able to reproduce the problem that Markus Sch?pflin found: Markus Sch?pflin wrote:
And I found that... Scott Schurr wrote prematurely:
I'm using the Microsoft 32-bit Compiler, Version 13.00.9466, and I'm running into two different problems with 64 bit values: 1. So far I've been unable to make Marcus's problem go away. With 32-bit values I was able to fix this up by forcing the underlying type that I write to my enums. When I try this same fix in 64-bits nothing gets better. 2. The worse problem is that binary value values larger than 32 bits (8 nibbles) get their upper nibbles truncated. After a couple of tests it appears that, for this compiler, the largest supported enum value must fit in 32 bits. If that's correct, then my enum based calculations run out of steam on this compiler at 32 bits. Hmmph. Matt Calabrese's macro-based approach is looking more appealing, at least as far as 64-bit support goes. Scott Schurr

Scott Schurr wrote:
Have you tried an approach that does not use enums. You can either use a maximum-size integer: struct binary_int { #if BOOST_HAS_INT64 // Verify this static const uint64_t value = ...; #else static const unsigned long value = ...; #endif }; or you could do something like: template< int b1, int b2 > struct binary_int { typedef unsigned short type; static const type value = ...; }; template< int b1, int b2, ..., int b4 > struct binary_int { typedef unsigned long type; static const type value = ...; }; template< int b1, int b2, ..., int b8 > struct binary_int { typedef uint64_t type; static const type value = ...; }; Note that I haven't had chance to look at the implementation, so I could be hedding in completely the wrong direction. Also note that the standard says that it is perfectly legal to use static const integer_type val = some_static_expression; It is only for broken compilers (read VC6) where you need to use enum { val = some_static_expression }; If you want to retain the portability to older compilers, you can use the enum trick for < 32-bits and then do #if COMPILER_IS_NOT_BROKEN template< int b1, int b2, ..., int b8 > struct binary_int { typedef uint64_t type; static const type value = ...; }; #endif
Matt Calabrese's macro-based approach is looking more appealing, at least as far as 64-bit support goes.
At the moment :). - Reece

Really, there's no reason not to use BOOST_STATIC_CONSTANT (include boost/config.hpp). It replaces the integer static constant type with an enum on broken compilers and uses a more type-specific solution on standard ones. You can determine which underlying integer type to use based on how many nibbles are provided compared to the type traits of an implementation's integer types (use ::boost::uint_t and ::boost::int_t in boost/integer.hpp). Unfortunately, the user still wouldn't have direct control over what the underlying value_type is. For instance, what if they want a small value to be an unsigned long, even though an unsigned int is capable of holding such a value. Currently, you'd have to use a cast. Alternatively, you could have the user pass the prefered type to the template as well, and have instantiations use that type internally. However, if the overall goal includes being at least somewhat consistent with the functionality and useability of literals, you reach a barrier with a template version, since the formation of standard literals simply uses integer suffixes. With the macro solution you use the form BOOST_SUFFIXED_BINARY_LITERAL( 101 010101, UL ) and are able to provide any standard C++ integer suffixes. In addition, you can even use any suffixes provided as extensions for a given compiler. So not only do you get the functionality of more type-controlled literals, but you also have more consistency with standard C++ integer literals when doing so. Of course, I'm at least somewhat biased since I developed the macro version, but I'm not certain that I see any benefits of using a template here other than perhaps a religious hatred of all macros, even when used appropriately. -- -Matt Calabrese

Also, if the template version is chosen, may I suggest making the default constructor public, typedefing an equivalent integer constant to "type", typedefing the underlying value type to "value_type", and overloading conversion to the value_type, such that instantiations of the template are also valid Boost.MPL constants? -- -Matt Calabrese

--- Reece Dunn wrote:
Or you can use #include <boost/config.hpp> #include <boost/cstdint.hpp> template <...> struct binary_int { BOOST_STATIC_CONSTANT(uint64_t, value = ...); }; Cromwell D. Enage __________________________________ Yahoo! Music Unlimited Access over 1 million songs. Try it free. http://music.yahoo.com/unlimited/

Guys, please, we have BOOST_STATIC_CONSTANT for this: BOOST_STATIC_CONSTANT(type, value = x); We also have config-macros to detect the presence of long long and whether 64-bit integers can be used in integral-constant-expressions. For portablity you should use long long and the uLL suffix, and not the Microsoft-specific ui64 suffix (versions of VC++ that don't support long long, don't support 64-bit constant expressions anyway so you don't loose anything by going down this route). John.
participants (5)
-
Cromwell Enage
-
John Maddock
-
Matt Calabrese
-
Reece Dunn
-
Scott Schurr