How to make is_arithmetic true for a UDT

I am facing the need to get my User Defined Type to return true from boost::is_arithmetic (This is to meet a check for autoprefixing in Boost.Units) There was some discussion on this issue before, http://lists.boost.org/boost-users/2007/10/31538.php but I am not clear if it reached a satisfactory conclusion. (Nor that I fully understand what is being proposed). A cut-down example is a Trivial UDT that does exactly same as double. (My actual example has template parameter for floating-point type of two members, a value and an uncertainty, and others). Suggestions? Paul -- - Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

I am facing the need to get my User Defined Type to return true from
boost::is_arithmetic
You don't, a UDT is not an arithmetic type (according to the type system which is what type_traits honors) it's a class type.
(This is to meet a check for autoprefixing in Boost.Units)
Looks like there are two places this is used in Units - and both are implementation details - for auto-prefixing looks like you need to overload autoprefix_norm for your type. The other use is in is_non_narrowing_conversion, which you would [partially-] specialize for your type. Hope that makes sense, John.

-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of John Maddock Sent: Thursday, July 12, 2012 10:32 AM To: boost-users@lists.boost.org Subject: Re: [Boost-users] How to make is_arithmetic true for a UDT
I am facing the need to get my User Defined Type to return true from
boost::is_arithmetic
You don't, a UDT is not an arithmetic type (according to the type system which is what type_traits honors) it's a class type.
(This is to meet a check for autoprefixing in Boost.Units)
Looks like there are two places this is used in Units - and both are implementation details - for auto- prefixing looks like you need to overload autoprefix_norm for your type. The other use is in is_non_narrowing_conversion, which you would [partially-] specialize for your type.
Well I finally managed to string enough neurons together to write // Specialization of autoprefix_norm for boost::units::measurement<Y> // See io.hpp // This is required to get autoprefix to work with this class. template<class Y> typename autoprefix_norm_impl<boost::units::measurement<Y>, true>::type autoprefix_norm(const boost::units::measurement<Y> & arg) { return autoprefix_norm_impl<Y, true>::call(arg); } and that does the trick :-)) quantity<length, measurement<double> > biglen(measurement<double>(12345.0,123.0)*meters); autoscaled = 12.345(+/-0.123) km so many thanks. But I'm still not clear when I could need the non-narrowing conversion in Boost.units quantity.hpp. I can see the need for this template<> struct is_non_narrowing_conversion<long double, double> : mpl::false_ {}; So would I need template<> struct is_non_narrowing_conversion<measurement< double>, double> : mpl::true_ {}; but template<> struct is_non_narrowing_conversion<measurement<long double>, double> : mpl::false_ {}; (though the existence of more than one FP type in the class, means that one needs to call measurement value() function to get a double, so the answer always false?). Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

Well I finally managed to string enough neurons together to write
// Specialization of autoprefix_norm for boost::units::measurement<Y> // See io.hpp // This is required to get autoprefix to work with this class. template<class Y> typename autoprefix_norm_impl<boost::units::measurement<Y>, true>::type autoprefix_norm(const boost::units::measurement<Y> & arg) { return autoprefix_norm_impl<Y, true>::call(arg); }
and that does the trick :-))
Hold on a second, doesn't that just tell Units to treat all T's as if they're double? Or is the type measurement your type? In any case autoprefix_norm_impl<T, true>::type appears to be always double, what happens if the UDT can't fit in a double? There's also a distinct lack of documentation on this, this page: http://www.boost.org/doc/libs/1_50_0/doc/html/boost_units/Reference.html mentions autoprefix_norm, but doesn't say what an overload should actually do :-(
quantity<length, measurement<double> > biglen(measurement<double>(12345.0,123.0)*meters); autoscaled = 12.345(+/-0.123) km
so many thanks.
But I'm still not clear when I could need the non-narrowing conversion in Boost.units quantity.hpp.
Nor me, there's no docs on this at all. I think it would help a great deal if the Units guys could chime in here and/or and a section on using Units with UDT's. John.

Well I finally managed to string enough neurons together to write
// Specialization of autoprefix_norm for boost::units::measurement<Y> // See io.hpp // This is required to get autoprefix to work with this class. template<class Y> typename autoprefix_norm_impl<boost::units::measurement<Y>, true>::type autoprefix_norm(const boost::units::measurement<Y> & arg) { return autoprefix_norm_impl<Y, true>::call(arg); }
and that does the trick :-))
Hold on a second, doesn't that just tell Units to treat all T's as if they're double? Or is the type measurement your type?
In any case autoprefix_norm_impl<T, true>::type appears to be always double, what happens if the UDT can't fit in a double?
There's also a distinct lack of documentation on this, this page: http://www.boost.org/doc/libs/1_50_0/doc/html/boost_units/Reference.html mentions autoprefix_norm, but doesn't say what an overload should actually do :-(
I'll let Steven address the autoprefixing stuff as that is his work...
quantity<length, measurement<double> > biglen(measurement<double>(12345.0,123.0)*meters); autoscaled = 12.345(+/-0.123) km
so many thanks.
But I'm still not clear when I could need the non-narrowing conversion in Boost.units quantity.hpp.
Nor me, there's no docs on this at all.
I think it would help a great deal if the Units guys could chime in here and/or and a section on using Units with UDT's.
Unfortunately, conversions and UDTs are a particularly difficult area since it is difficult to know in all cases how one should promote the UDT or construct an appropriately promoted UDT. For example, converting integer feet to integer meters doesn't work, so the resulting quantity needs to be a double. We can special case these types of conversions, but there is no obvious way to know a priori how to do the promotion for an arbitrary UDT... Suggestions, of course, are always welcome. Matthias

Unfortunately, conversions and UDTs are a particularly difficult area since it is difficult to know in all cases how one should promote the UDT or construct an appropriately promoted UDT. For example, converting integer feet to integer meters doesn't work, so the resulting quantity needs to be a double. We can special case these types of conversions, but there is no obvious way to know a priori how to do the promotion for an arbitrary UDT... Suggestions, of course, are always welcome.
1) Define a trait (maybe you already have?) that handles the promotions. 2) Provide defaults for built in types. 3) Document it, and provide an example, plus some concept checks. The defaults could even be smart - for example if numeric_limits is specialized for a type, then: * If the an integer type is arbitrary precision (unbounded in numeric_limits speak), then there's no need to promote. * If the type is convertible to double, then you could use that conversion. But what happens for integers with lots of digits - for example do you "promote" long long to double? If so you're gaining range but throwing away digits which may not be what the user wants. Not sure how much this helps, John.

-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Matthias Schabel Sent: Tuesday, July 17, 2012 6:21 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [units] How to use units with UDT's: was How to make is_arithmetic true for a UDT
Well I finally managed to string enough neurons together to write
// Specialization of autoprefix_norm for boost::units::measurement<Y> // See io.hpp // This is required to get autoprefix to work with this class. template<class Y> typename autoprefix_norm_impl<boost::units::measurement<Y>, true>::type autoprefix_norm(const boost::units::measurement<Y> & arg) { return autoprefix_norm_impl<Y, true>::call(arg); }
and that does the trick :-))
Hold on a second, doesn't that just tell Units to treat all T's as if they're double? Or is the type measurement your type?
In any case autoprefix_norm_impl<T, true>::type appears to be always double, what happens if the UDT can't fit in a double?
There's also a distinct lack of documentation on this, this page: http://www.boost.org/doc/libs/1_50_0/doc/html/boost_units/Reference.ht ml mentions autoprefix_norm, but doesn't say what an overload should actually do :-(
I'll let Steven address the autoprefixing stuff as that is his work...
quantity<length, measurement<double> > biglen(measurement<double>(12345.0,123.0)*meters); autoscaled = 12.345(+/-0.123) km
so many thanks.
But I'm still not clear when I could need the non-narrowing conversion in Boost.units quantity.hpp.
Nor me, there's no docs on this at all.
I think it would help a great deal if the Units guys could chime in here and/or and a section on using Units with UDT's.
Unfortunately, conversions and UDTs are a particularly difficult area since it is difficult to know in all cases how one should promote the UDT or construct an appropriately promoted UDT. For example, converting integer feet to integer meters doesn't work, so the resulting quantity needs to be a double. We can special case these types of conversions, but there is no obvious way to know a priori how to do the
promotion for
an arbitrary UDT... Suggestions, of course, are always welcome.
My need is for UDTs that have more than one element, typified by the examples of mean and standard deviation in measurement.hpp. I hope that these work OK because all these are floating-point types (something that could be - or perhaps already is - checked at compile time). I'll provide feedback when I have experience using them. With John's assistance, I have now got autoprefixing to work for my purposes by specializing autoprefix_norm. I think it would be worth adding this specialization to the measurement.hpp example and will do this if you agree. A one line example could be added to the kitchen sink example to show autoprefixing in action with the existing UDT measurement. It may be worth noting that this caused me some grief because the namespace of autoprefix_impl is boost::units, but the namespace of autoprefix_norm must be specialized in *my* UDT's namespace. Obvious in hindsight but caused some head scratching :-( Paul
participants (3)
-
John Maddock
-
Matthias Schabel
-
Paul A. Bristow