
Hello, Recently I was creating a new numeric type which I wanted to use along with boost::numeric_cast. I read over the docs and examples and found that it seemed to support (at least partially) the notion of policy driven casting operations. I was unable to figure out how one might use a custom conversion or overflow policy along with the actual boost::numeric_cast<N>(x) function. In the end I created a workaround which seemed to work nicely: template <typename ConversionTraits, typename EnableIf = void> struct numeric_cast_traits { typedef def_overflow_handler overflow_handler; typedef UseInternalRangeChecker range_checker; typedef Trunc < typename ConversionTraits::source_type > rounding_policy; }; template <typename Target, typename Source> inline Target numeric_cast( Source arg ) { typedef boost::numeric::conversion_traits<Target, Source> conv_traits; typedef numeric_cast_traits< conv_traits > cast_traits; typedef boost::numeric::converter < Target , Source , conv_traits , typename cast_traits::overflow_handler , typename cast_traits::rounding_policy , boost::numeric::raw_converter< conv_traits > , typename cast_traits::range_checker
converter; return converter()(arg); }
This change allowed me to easily customize the numeric_cast function for individual conversion types. Did I miss something in the official library? If not, would this change be something good to go in? Regards, Brandon Kohn

First of all, it looks like the numeric_cast library is not maintained any more, so you won't get a fast answer. 2011/6/16 Brandon Kohn <blkohn@hotmail.com>:
This change allowed me to easily customize the numeric_cast function for individual conversion types.
Did I miss something in the official library? If not, would this change be something good to go in?
There is a chapter called "Type Requirements and User-defined-types support" in numeric_cast library, that describes how to make your new numeric type usable with numeric_cast. Chapter "converter<> function object" describes how to use boost::numeric::converter with different casting polices. Did I answered your questions or have i missed something? Best regards, Antony Polukhin

On 6/21/2011 4:33 PM, Antony Polukhin wrote:
First of all, it looks like the numeric_cast library is not maintained any more, so you won't get a fast answer.
I was hoping the community might step up on this.
There is a chapter called "Type Requirements and User-defined-types support" in numeric_cast library, that describes how to make your new numeric type usable with numeric_cast.
I've read it.
Chapter "converter<> function object" describes how to use boost::numeric::converter with different casting polices.
Did I answered your questions or have i missed something?
I think you've missed something. Here is the code for numeric_cast that is in boost: template<typename Target, typename Source> inline Target numeric_cast ( Source arg ) { typedef boost::numeric::converter<Target,Source> Converter ; return Converter::convert(arg); } Note the way Converter is defined. Here is the definition of converter: template<class T, class S, class Traits = conversion_traits<T,S>, class OverflowHandler = def_overflow_handler, class Float2IntRounder = Trunc< BOOST_DEDUCED_TYPENAME Traits::source_type> , class RawConverter = raw_converter<Traits>, class UserRangeChecker = UseInternalRangeChecker > struct converter : convdetail::get_converter_impl<Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker >::type { As written there is no way for a user to specify a different overflow handler, rounding policy, or range checker. The defaults are always used when numeric_cast is called. Regards, Brandon Kohn

Hi Brandon, This was a known problem and I like youtr solution :) If you can update the docs and test, please go ahead and submit the patch... ONCE the release brach is open for 1.48, of course Best regards -- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

On 6/22/2011 8:39 AM, Fernando Cacciola wrote:
Hi Brandon,
This was a known problem and I like youtr solution :)
If you can update the docs and test, please go ahead and submit the patch... ONCE the release brach is open for 1.48, of course
Ok, I'll put it together. Cheers, Brandon

2011/6/22 Brandon Kohn <blkohn@hotmail.com>:
As written there is no way for a user to specify a different overflow handler, rounding policy, or range checker. The defaults are always used when numeric_cast is called.
May be i am missing something, but I see no problem here. numeric_cast is designed to be as simple as possible. When the default polices are not what you need, you just define your own converter function via template<typename Target, typename Source> inline Target my_numeric_cast ( Source arg ) { using namespace boost::numeric; typedef boost::numeric::converter<Target, Source, conversion_traits<Target, Source>, silent_overflow_handler > Converter ; return Converter::convert(arg); } or just directly call the required conversion function: converter<Target, Source, conversion_traits<Target, Source>, silent_overflow_handler >::convert(arg); So you do not need to create your own numeric_cast_traits. All you need to do, as a developer of a new numeric type, is just overload rounding functions for your type, add your type to std::numeric_limits. Using your solution, we will break thecurrent behavior of numeric_cast function and the code that uses it. Library user won`t know, will the numeric_cast truncate or round via ceil, will it throw on overflows of silently ignore them. It will add more mess to the library, and less users will use it. Best regards, Antony Polukhin

On 6/22/2011 9:40 AM, Antony Polukhin wrote:
May be i am missing something, but I see no problem here. numeric_cast is designed to be as simple as possible. When the default polices are not what you need, you just define your own converter function via
template<typename Target, typename Source> inline Target my_numeric_cast ( Source arg ) { using namespace boost::numeric; typedef boost::numeric::converter<Target, Source, conversion_traits<Target, Source>, silent_overflow_handler> Converter ; return Converter::convert(arg); }
The problem with that solution is that it avoids an obvious problem when you have a lot of generative code using boost::numeric_cast. One would have to write a level of indirection to dispatch to either numeric_cast or my_numeric_cast depending on the conversion traits. If you have a lot of code with boost::numeric_cast that is quite a pain. Plus I think it is unnecessary.
or just directly call the required conversion function: converter<Target, Source, conversion_traits<Target, Source>, silent_overflow_handler>::convert(arg);
This really is no different than the solution my_numeric_cast above. The same problems apply.
So you do not need to create your own numeric_cast_traits. All you need to do, as a developer of a new numeric type, is just overload rounding functions for your type, add your type to std::numeric_limits.
I don't think this is good enough give the above stated issues.
Using your solution, we will break thecurrent behavior of numeric_cast function and the code that uses it. Library user won`t know, will the numeric_cast truncate or round via ceil, will it throw on overflows of silently ignore them. It will add more mess to the library, and less users will use it.
The defaults of numeric_cast_traits definition conform to the current behavior. It would only change if the users customize it. From that angle I think the greater flexibility comes with a bit more responsibility on the users side. Seems like a fair trade-off to me. Regards, Brandon

On 6/22/2011 8:39 AM, Fernando Cacciola wrote:
Hi Brandon,
This was a known problem and I like youtr solution :)
If you can update the docs and test, please go ahead and submit the patch... ONCE the release brach is open for 1.48, of course
Best regards
From whom do I need to request permission to submit a patch to the 1.48 branch? (It's my first time submitting a patch...) :) Thanks Brandon

On 6/22/2011 8:39 AM, Fernando Cacciola wrote:
Hi Brandon,
This was a known problem and I like youtr solution :)
If you can update the docs and test, please go ahead and submit the patch... ONCE the release brach is open for 1.48, of course
Best regards
I have a patch I would like to submit to the 1.48 branch as Fernando requested. From whom do I need to get permission to make the submission? Thanks, Brandon

On Aug 3, 2011, at 8:35 AM, Brandon Kohn <blkohn@hotmail.com> wrote:
I have a patch I would like to submit to the 1.48 branch as Fernando requested. From whom do I need to get permission to make the submission?
You need to get Fernando to apply the patch or if you're willing, ask to be a co-maintainer of the lib. HTH G

On 8/3/2011 11:30 AM, Gordon Woodhull wrote:
On Aug 3, 2011, at 8:35 AM, Brandon Kohn<blkohn@hotmail.com> wrote:
I have a patch I would like to submit to the 1.48 branch as Fernando requested. From whom do I need to get permission to make the submission?
You need to get Fernando to apply the patch or if you're willing, ask to be a co-maintainer of the lib.
Fernando posted this message previously: On 6/22/2011 8:39 AM, Fernando Cacciola wrote:
Hi Brandon,
This was a known problem and I like youtr solution :)
If you can update the docs and test, please go ahead and submit the patch... ONCE the release brach is open for 1.48, of course
Best regards
Seems he expected me to submit the patch. Regards, Brandon

On Aug 3, 2011, at 11:34 AM, Brandon Kohn <blkohn@hotmail.com> wrote:
Seems he expected me to submit the patch.
He probably thought you already had trunk access. You'll need access in order to follow up on any problems that crop up. IMO it would be best for you to sign up to as a maintainer of the lib ... ask Fernando for permission and then ask the moderators (boost-owner@...) for the account ... if you're willing to take the responsibility. HTH G

On 8/3/2011 3:42 PM, Gordon Woodhull wrote:
On Aug 3, 2011, at 11:34 AM, Brandon Kohn<blkohn@hotmail.com> wrote:
Seems he expected me to submit the patch.
He probably thought you already had trunk access. You'll need access in order to follow up on any problems that crop up. IMO it would be best for you to sign up to as a maintainer of the lib ... ask Fernando for permission and then ask the moderators (boost-owner@...) for the account ... if you're willing to take the responsibility.
Indeed I thought he had write permissions already. I would be happy to have Brandon as a maintainer, so I'm formally giving Brandon permision to take on the task. Best -- --- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

Brandon Kohn wrote:
Hello,
Recently I was creating a new numeric type which I wanted to use along with boost::numeric_cast. I read over the docs and examples and found that it seemed to support (at least partially) the notion of policy driven casting operations. I was unable to figure out how one might use a custom conversion or overflow policy along with the actual boost::numeric_cast<N>(x) function. In the end I created a workaround which seemed to work nicely:
template <typename ConversionTraits, typename EnableIf = void> struct numeric_cast_traits { typedef def_overflow_handler overflow_handler; typedef UseInternalRangeChecker range_checker; typedef Trunc < typename ConversionTraits::source_type > rounding_policy; };
Hi, I would prefer that numeric_cast_traits is templated with typename Target, typename Source, typename EnableIf = void as it seems to me more natural than using another trait as parameter. Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/numeric-cast-tp3602499p3617554.html Sent from the Boost - Dev mailing list archive at Nabble.com.

On 6/22/2011 12:50 PM, Vicente Botet wrote:
I would prefer that numeric_cast_traits is templated with
typename Target, typename Source, typename EnableIf = void
as it seems to me more natural than using another trait as parameter.
Good point. I'll do that in my proposal. Cheers, Brandon

2011/6/22 Brandon Kohn <blkohn@hotmail.com>:
The defaults of numeric_cast_traits definition conform to the current behavior. It would only change if the users customize it. From that angle I think the greater flexibility comes with a bit more responsibility on the users side. Seems like a fair trade-off to me.
Well, then here is some ideas. I am really afraid that some user will define such trait in header file. Then all the code above the included header file will use the old conversion trait, and below - the new trait. Include files became dependent from their order. It is really error prone. User can forget about the trait, change the inclusion order and get some really hard detectable errors. So it would be more save not to modify the behavior of boost::numeric_cast<N>(x) function, but rather create function with some other name, for example boost::numeric_traited_cast<N>(x) and create a separate namespace in boost::numeric for the traits. It would be better not to return converter()(arg); but return converter::convert(arg);. It won`t call the constructor of the converter and give better performance on some old/bad compilers. Best regards, Antony Polukhin

Antony Polukhin wrote:
2011/6/22 Brandon Kohn <blkohn@hotmail.com>:
The defaults of numeric_cast_traits definition conform to the current behavior. It would only change if the users customize it. From that angle I think the greater flexibility comes with a bit more responsibility on the users side. Seems like a fair trade-off to me.
Well, then here is some ideas.
I am really afraid that some user will define such trait in header file. Then all the code above the included header file will use the old conversion trait, and below - the new trait. Include files became dependent from their order. It is really error prone. User can forget about the trait, change the inclusion order and get some really hard detectable errors. So it would be more save not to modify the behavior of boost::numeric_cast<N>(x) function, but rather create function with some other name, for example boost::numeric_traited_cast<N>(x) and create a separate namespace in boost::numeric for the traits.
You are right that changing the implementation in this way can break some code in the future. Maybe we should be more conservative. The library has already a namespace boost::numeric so what about boost::numeric::convert_to/convert instead? Best Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/numeric-cast-tp3602499p3617618.html Sent from the Boost - Dev mailing list archive at Nabble.com.

On 6/22/2011 2:15 PM, Vicente Botet wrote:
Antony Polukhin wrote:
2011/6/22 Brandon Kohn<blkohn@hotmail.com>:
The defaults of numeric_cast_traits definition conform to the current behavior. It would only change if the users customize it. From that angle I think the greater flexibility comes with a bit more responsibility on the users side. Seems like a fair trade-off to me.
Well, then here is some ideas.
I am really afraid that some user will define such trait in header file. Then all the code above the included header file will use the old conversion trait, and below - the new trait. Include files became dependent from their order. It is really error prone. User can forget about the trait, change the inclusion order and get some really hard detectable errors. So it would be more save not to modify the behavior of boost::numeric_cast<N>(x) function, but rather create function with some other name, for example boost::numeric_traited_cast<N>(x) and create a separate namespace in boost::numeric for the traits.
You are right that changing the implementation in this way can break some code in the future. Maybe we should be more conservative.
The library has already a namespace boost::numeric so what about boost::numeric::convert_to/convert instead?
But this won't address the problem Brandon is trying to solve: namely, to allow numeric_cast<> --and no other function-- to really work with custom numeric types (which might have specific policy requirements). I do understand Antony's concern, but I think is a bit of a red herring. That is, I doubt it could really happen in practice, even though it technically could. In any case, what is really important IMO is the keep the behaviour stable for the fundamental types. Thus a reasonable balance could be, IMO, that the additional traits is given already specialized for the fundamental types. This way, the extensibility is only really available for custom types. Sort of the way numeric_limits<> works. Best -- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

Fernando Cacciola wrote:
But this won't address the problem Brandon is trying to solve: namely, to allow numeric_cast<> --and no other function-- to really work with custom numeric types (which might have specific policy requirements).
I do understand Antony's concern, but I think is a bit of a red herring. That is, I doubt it could really happen in practice, even though it technically could.
In the normal case, the UDT header would include the specialization so anytime the UDT is defined, the specialization would be visible. I suppose one might wish to avoid the numeric_cast dependency and put the specialization in another header, though. That would lead to the problem Antony was referring to.
In any case, what is really important IMO is the keep the behaviour stable for the fundamental types.
+1
Thus a reasonable balance could be, IMO, that the additional traits is given already specialized for the fundamental types. This way, the extensibility is only really available for custom types. Sort of the way numeric_limits<> works.
That seems reasonable. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Hello, Here is a patch with my proposed changes. This includes docs and tests. Let me know what you guys think. In particular are there any extra tests I should include? Thanks, Brandon

Hi Brandon, It looks fine to me (except maybe for the #pragma once... is that properly supported on all supported compilers?) BTW, looking at the diff, I realize that this utility is 10 years old already! :) -- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

On 6/23/2011 3:41 PM, Fernando Cacciola wrote:
Hi Brandon,
It looks fine to me (except maybe for the #pragma once... is that properly supported on all supported compilers?)
Ah, right. We use that at my work (all MSVC). So I'm acclimated. I'll remove those.
BTW, looking at the diff, I realize that this utility is 10 years old already! :)
Yeah, great stuff! :)

[Fernando Cacciola]
It looks fine to me (except maybe for the #pragma once... is that properly supported on all supported compilers?)
[Brandon Kohn]
Ah, right. We use that at my work (all MSVC). So I'm acclimated. I'll remove those.
Actually, the best thing to do is this: #ifndef MYPROJECT_MYDIRECTORY_FOOBAR_HPP #define MYPROJECT_MYDIRECTORY_FOOBAR_HPP #ifdef _MSC_VER #pragma once #endif // _MSC_VER meow; #endif // MYPROJECT_MYDIRECTORY_FOOBAR_HPP This way, all compilers get the portable idempotency guard. Because it's on the outside, GCC (and possibly other compilers) will magically recognize it and avoid opening the header file twice. And the #pragma once for MSVC also instructs it to avoid opening the header file twice, which can improve build perf and can't hurt. Stephan T. Lavavej Visual C++ Libraries Developer

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Stephan T. Lavavej Sent: Thursday, June 23, 2011 10:43 PM To: boost@lists.boost.org Subject: Re: [boost] numeric_cast
[Fernando Cacciola]
It looks fine to me (except maybe for the #pragma once... is that properly supported on all supported compilers?)
[Brandon Kohn]
Ah, right. We use that at my work (all MSVC). So I'm acclimated. I'll remove those.
Actually, the best thing to do is this:
#ifndef MYPROJECT_MYDIRECTORY_FOOBAR_HPP #define MYPROJECT_MYDIRECTORY_FOOBAR_HPP
#ifdef _MSC_VER #pragma once #endif // _MSC_VER
meow;
#endif // MYPROJECT_MYDIRECTORY_FOOBAR_HPP
This way, all compilers get the portable idempotency guard. Because it's on the outside, GCC (and
Sorry for last response (I have just got back from holiday :-) I suspect we are all agreed this is correct? If so should it go into our Boost style 'recommendations' docs somewhere? Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com possibly
other compilers) will magically recognize it and avoid opening the header file twice. And the #pragma once for MSVC also instructs it to avoid opening the header file twice, which can improve build perf and can't hurt.
Stephan T. Lavavej Visual C++ Libraries Developer _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

2011/7/11 Paul A. Bristow <pbristow@hetp.u-net.com>:
If so should it go into our Boost style 'recommendations' docs somewhere?
If you keep the behaviour stable for the fundamental types, then I have no objections. It will be a good feature! But the final decision must take the maintainer. Best regards, Antony Polukhin

On 7/11/2011 12:25 PM, Antony Polukhin wrote:
2011/7/11 Paul A. Bristow<pbristow@hetp.u-net.com>:
If so should it go into our Boost style 'recommendations' docs somewhere?
If you keep the behaviour stable for the fundamental types, then I have no objections. It will be a good feature! But the final decision must take the maintainer.
Best regards, Antony Polukhin
That's great. :) I've put together a more streamlined patch that includes a preprocessed set of traits for the fundamental types. I chose to explicitly generate them from macros rather than use enable_if tricks to avoid compile time costs. One problem I foresee is how to arrive at a unique set of fundamental types for each compiler. I used boost/cstdint.hpp and the definitions there for the integral type (u/int8_t etc.) I found something that was a bit of a surprise though on msvc10. The 'char' type is not the same as int8_t (signed char) or uint8_t(unsigned char). I would have expected the former. I explicitly added char specialization to the args sent to the code generation macros, but I expect this won't be correct for all compilers. Cheers, Brandon

Brandon Kohn wrote:
I found something that was a bit of a surprise though on msvc10. The 'char' type is not the same as int8_t (signed char) or uint8_t(unsigned char). I would have expected the former. I explicitly added char specialization to the args sent to the code generation macros, but I expect this won't be correct for all compilers.
There are three char types in C/C++: signed char, unsigned char, and char. The latter may be represented as either of the other two, but which is implementation defined. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com ________________________________ IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On Thu, 14 Jul 2011 22:05:12 +0600, Brandon Kohn <blkohn@hotmail.com> wrote:
[snip] I found something that was a bit of a surprise though on msvc10. The 'char' type is not the same as int8_t (signed char) or uint8_t(unsigned char). I would have expected the former. I explicitly added char specialization to the args sent to the code generation macros, but I expect this won't be correct for all compilers.
MSVC is right. According to 3.9.1/1 of 14882:2003, "... Plain char, signed char, and unsigned char are three distinct types. ... and "... In any particular implementation, a plain char object can take on either the same values as a signed char or an unsigned char; which one is implementation-defined. ..."

On 6/23/2011 3:41 PM, Fernando Cacciola wrote:
Hi Brandon,
It looks fine to me (except maybe for the #pragma once... is that properly supported on all supported compilers?)
BTW, looking at the diff, I realize that this utility is 10 years old already! :)
I sent a post before, but it seems gmane didn't process it correctly. I have a version that I think could go in the 1.48 branch, but I don't know whom I should ask for commit permission. Could someone point me in the proper direction? Thanks :) Brandon
participants (9)
-
Antony Polukhin
-
Brandon Kohn
-
Fernando Cacciola
-
Gordon Woodhull
-
Ilya Sokolov
-
Paul A. Bristow
-
Stephan T. Lavavej
-
Stewart, Robert
-
Vicente Botet