
-What is your evaluation of the design? It makes sense to me to have a rigid compile-time system for this, the design is simple and very intuitive. I was able to use the basic unit conversions without even reading the docs, and everything shows up just where you expect it. The library does require a lot of typing, but this is going to automatically go away once the auto keyword becomes standard. I do disagree with previous comments on the evilness of the mutating value() method. In particular, if the unit base is a user-defined type, then there is no other way for the user to access the contained object's member functions, so I don't see how you can get away without having value(). (As a reasonable example, you might want to use units with a boost::rational<int> data type, but without a mutating value(), you can't call boost::rational<int>::assign() anymore). I think this deficiency would cause people either to not use units, or to use a quantity<Q, boost::reference_wrapper<T> > instead, which is annoying and suffers from the same dangers anyway. Also, quantity<> should pass through operator++ and operator-- in addition to the other arithmetic operators. I was surprised to find that the prefixes kilo, mega, etc, are in namespace SI. They are equally useful for CGS and for user defined systems; perhaps they should be in a new namespace boost::units::prefix, since they are just static constants? Also, I was surprised that units/systems/si/prefixes.hpp was not included by units/systems/si.hpp, since I thought that was going to be a "catch-all" header. -What is your evaluation of the implementation? I didn't look in a lot of detail, enough to tell that there is good re-use of Boost metaprogramming libraries, etc, and the code seems easy to follow. It compiles in a reasonable amount of time. One thing I noticed is that the code does not use BOOST_STATIC_CONSTANT. Is this under the assumption that compilers which need BOOST_STATIC_CONSTANT won't compile the code anyway? That's probably correct I guess. I was surprised by the following behavior: #include <iostream> #include <boost/units/io.hpp> #include <boost/units/systems/si.hpp> #include <boost/units/systems/cgs.hpp> #include <boost/units/systems/si/prefixes.hpp> using namespace boost::units; int main() { quantity<CGS::force> F0 = 20 * CGS::dyne; quantity<SI::force> F1 = quantity_cast<SI::force>(F0); quantity<SI::force> F2 = quantity_cast<SI::force>(20 * CGS::dyne); quantity<SI::force> F3(F0); //quantity<SI::force> F4 = F0; //quantity<SI::force> F5(20 * CGS::dyne); //quantity<SI::force> F6 = 20 * CGS::dyne; std::cout << F1 << '\n' << F2 << '\n' << F3 << '\n'; } Firstly, I would have expected all 6 initializations of F1-F6 to do exactly the same thing. The last three do not compile at all, though. I think it is particularly surprising that there is a difference between F3 and F4. Most users are used to these two syntaxes being absolutely identical in meaning. I haven't looked at the implementation in detail, I'm just pointing out that this is a surprising feature. Also problematic is F2, which does compile, albeit with a warning, but then does the wrong thing at run time. The output of this program is: 1e-05 m kg s^(-2) 0 m kg s^(-2) 1e-05 m kg s^(-2) This appears to be related to the fact that in the initialization of F0, there is an implicit conversion from the int (20) to double. If I change the int to a double (20.) , then the code compiles without warnings and does the right thing. Similarly, changing the int to a double allows F5 to compile, but again, the equivalent-looking F6 does not. BTW, the warning issued by gcc is: ../../../boost/units/conversion.hpp: In static member function `static boost::units::quantity<boost::units::unit<Dim1, boost::units::homogeneous_system<S2> >, Y> boost::units::conversion_helper<boost::units::quantity<boost::units::unit<Dim1, boost::units::homogeneous_system<S> >, Y>, boost::units::quantity<boost::units::unit<Dim1, boost::units::homogeneous_system<S2> >, Y> >::convert(const boost::units::quantity<boost::units::unit<Dim1, boost::units::homogeneous_system<S> >, Y>&) [with S1 = boost::units::CGS::system_tag, S2 = boost::units::SI::system_tag, Dim1 = boost::units::force_type, Y = int]': ../../../boost/units/quantity.hpp:91: instantiated from `boost::units::quantity<Unit, Y>::quantity(const boost::units::quantity<boost::units::unit<Dim2, System2>, YY>&, typename boost::disable_if<typename boost::units::is_implicitly_convertible<boost::units::unit<Dim2, System2>, boost::units::unit<typename boost::units::get_dimension<T>::type, typename boost::units::get_system<T>::type> >::type, void>::type*) [with System2 = boost::units::CGS::system, Dim2 = boost::units::force_type, YY = int, Unit = boost::units::unit<boost::units::force_type, boost::units::SI::system>, Y = int]' ../../../boost/units/quantity.hpp:360: instantiated from `boost::units::quantity<boost::units::unit<Dim, System>, X> boost::units::quantity_cast_helper<boost::units::unit<Dim, System>, boost::units::quantity<Unit2, X> >::operator()(const boost::units::quantity<Unit2, X>&) [with X = int, System = boost::units::SI::system, Dim = boost::units::force_type, Unit2 = boost::units::unit<boost::units::force_type, boost::units::CGS::system>]' ../../../boost/units/quantity.hpp:378: instantiated from `typename boost::units::quantity_cast_helper<X, Y>::type boost::units::quantity_cast(const Y&) [with X = boost::units::SI::force, Y = boost::units::quantity<boost::units::unit<boost::units::force_type, boost::units::CGS::system>, int>]' t.cpp:14: instantiated from here ../../../boost/units/conversion.hpp:52: warning: passing `double' for converting 1 of `static boost::units::quantity<Unit, Y> boost::units::quantity<Unit, Y>::from_value(const Y&) [with Unit = boost::units::unit<boost::units::force_type, boost::units::SI::system>, Y = int]' -What is your evaluation of the documentation? The large number of examples is excellent. The documentation needs a lot more substance to it, particularly explaining surprising features of implicit conversions. -What is your evaluation of the potential usefulness of the library? I can see it being very useful. I myself am considering using it in the near future. One concern I have, is that I use a lot of C++ wrappers over legacy C libraries such as CLAPACK and ATLAS. I would still be able to use boost::units, provided I could count on sizeof(quantity<Q,T>) == sizeof(T), so that an array of quantitity<Q,T> would look the same in memory as an array of T. I doubt you would find any compiler where this is not the case, but it would be nice if the library could offer some sort of guarantee, since the standard doesn't, or at least comment on this issue in the docs. Another convenient option would be to put a static assert in the definition of quantity<> that the user could turn on via a #define if they want to be sure of this. -Did you try to use the library? With what compiler? Did you have any problems? The compile of cmath fails on gcc 3.4.4 on cygwin/MinGW and on gcc 3.4.6 on Linux because of undefined symbol __builtin_signbit in detail/cmath_gnu_impl.hpp line 195. This prohibits eg compilation of unit_example_11.cpp There are also a few source files missing terminating newlines, which produces a warning on some compilers. The library does not compile on earlier gcc versions as I mentioned in an earlier email, but this is not surprising. Other than cmath, the library compiled fine on gcc 3.4.{4,6} and 4.0.2. gcc 3.4.{4,6} was not able to optimize the runtime overhead entirely away. Without optimizations, the supplied timing example was about 10 times slower compared to the non-unit version. With optimization, it was only about 20% slower. On gcc 4.0.2, with optimization it was the same speed. - How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? Played around with it for a couple hours, didn't put in a lot of time reading the actual implementation. -Are you knowledgeable about the problem domain? Yes, I am knowledgeable about units/dimensional analysis. - Do you think the library should be accepted as a Boost library? Be sure to say this explicitly so that your other comments don't obscure your overall opinion. Yes, I think this library is a good and useful example of compile-time programming, and it should be accepted. I do have some concerns about the implicit conversions and initialization issues, but I think they probably just stem from my lack of understanding of some implementation issues, which means that improved docs would probably suffice to take care of them. I do think the one issue I mentioned above (the combination of quantity_cast and a conversion from int to double producing incorrect runtime behavior) qualifies as a bug, perhaps compiler-specific? -Lewis

I forgot one additional comment... for clarity, I would recommend eliminating the duplicate unit names (SI::meter, SI::meters, SI::metre, SI::metres, etc). For one thing, to maintain consistency, users might then feel obligated to do this in their own unit systems as well. I think it makes more sense to just pick a convention and stick with it, especially for the singular vs plural, which is really just a matter of taste, and users will learn to deal with whichever one the library writers pick :-). As for the alternate spellings, I guess if that's a political issue they could stay, but the plurals definitely seem gratuitous to me. -Lewis

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Lewis Hyatt Sent: 29 March 2007 00:09 To: boost@lists.boost.org Subject: Re: [boost] units: review
I forgot one additional comment... for clarity, I would recommend eliminating the duplicate unit names (SI::meter, SI::meters, SI::metre, SI::metres, etc). For one thing, to maintain consistency, users might then feel obligated to do this in their own unit systems as well. I think it makes more sense to just pick a convention and stick with it, especially for the singular vs plural, which is really just a matter of taste, and users will learn to deal with whichever one the library writers pick :-). As for the alternate spellings, I guess if that's a political issue they could stay, but the plurals definitely seem gratuitous to me.
As I recall, SI specifically says do NOT use the plurals. So I agree with this. (But it needs documenting with chapter and verse to head off those who try to be non-standard?). Paul --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

As I recall, SI specifically says do NOT use the plurals.
Paul, Do you have a reference for this?
So I agree with this. (But it needs documenting with chapter and verse to head off those who try to be non-standard?).
I'm not strongly attached to having plurals - any dissenters to the idea of removing them in favor of the singular forms? I think we should probably retain the alternate spellings, OTOH... Matthias

Just me but I disambiguate between "meter" and "meters". To me, "meter" implies the actual unit. This would tranlsates to a type in a units library. The word "meters" however implies a quantity measured in meters. This is different from "meter" as it implies a value. So I can rationalize the need for both forms. Eric.
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Matthias Schabel Sent: Thursday, March 29, 2007 9:43 AM To: boost@lists.boost.org Subject: Re: [boost] units: review
As I recall, SI specifically says do NOT use the plurals.
Paul,
Do you have a reference for this?
So I agree with this. (But it needs documenting with chapter and verse to head off those who try to be non-standard?).
I'm not strongly attached to having plurals - any dissenters to the idea of removing them in favor of the singular forms? I think we should probably retain the alternate spellings, OTOH...
Matthias
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Matthias Schabel Sent: 29 March 2007 16:43 To: boost@lists.boost.org Subject: Re: [boost] units: review
As I recall, SI specifically says do NOT use the plurals.
Paul,
Do you have a reference for this?
So I agree with this. (But it needs documenting with chapter and verse to head off those who try to be non-standard?).
I'm not strongly attached to having plurals - any dissenters to the idea of removing them in favor of the singular forms? I think we should probably retain the alternate spellings, OTOH...
http://en.wikipedia.org/wiki/International_System_of_Units The SI rule for pluralising units is that symbols of units are not pluralised[2], for example "25 kg" (not "25 kgs"). Reference 2 is Bureau International des Poids et Mesures (2006). "The International System of Units (SI)". 8th ed.. Retrieved on 2006-07-14. So this is quite specific and so I definitely think they should GO for SI units. Paul PS I understand what Eric Lemings is saying, but I think having both invites abuse and confusion. Keep It Simple Sir - stick to singular. --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

http://en.wikipedia.org/wiki/International_System_of_Units
The SI rule for pluralising units is that symbols of units are not pluralised[2], for example "25 kg" (not "25 kgs").
Reference 2 is
Bureau International des Poids et Mesures (2006). "The International System of Units (SI)". 8th ed.. Retrieved on 2006-07-14.
So this is quite specific and so I definitely think they should GO for SI units.
Of course, we're not talking about symbols of units (which, incidentally, are not pluralized in the library), but full names of units. The original rationale was that quantity<SI::length> q = 2*meters; reads a bit better than quantity<SI::length> q = 2*meter; If anything, I would argue that the singular cases are the edge cases, since you would only use them for the case of unit valued quantities : quantity<SI::length> q = 1*meter; and, by my reading, even this would be better plural : quantity<SI::length> q = 1.0*meters; Naturally, I'm eliding the multiplication in reading this expression... Anyway, as with many of these points, I'm not dogmatic. I see the merits of simplicity - how about I remove the singular cases? BTW, Paul, I hope you'll have a chance to give the library a formal review. We'd appreciate your input. Matthias

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Matthias Schabel Sent: Thursday, March 29, 2007 11:27 AM To: boost@lists.boost.org Subject: Re: [boost] units: review
...
units. The original rationale was that
quantity<SI::length> q = 2*meters;
reads a bit better than
quantity<SI::length> q = 2*meter;
I'm confused by this syntax. The intent here is to assign a quantity of 2 meters to an "anonymous" quantity of length, correct? If so, wouldn't the following syntax make more sense? quantity<SI::length> q = quantity<SI::meter>(2); The "2*meters" syntax just seems rather obscure. Likewise, a "measure", a quantity with a specified unit, should be constructed without the need for qualification. quantity<SI::meter> q (2); That is, the "2*meters" should not be required when the unit is already explicitly specified as part of the type. By the way, while meter is an SI unit and therefore belongs in the SI namespace, length is not an SI dimension hence the name "length" does not belong in the SI namespace. It should probably be elevated to the boost::units namespace. I don't believe there is such a thing as an "SI dimension"; i.e. other system of measurement (e.g. Imperial) have units of length as well. Eric.

I'm confused by this syntax. The intent here is to assign a quantity of 2 meters to an "anonymous" quantity of length, correct? If so, wouldn't the following syntax make more sense?
quantity<SI::length> q = quantity<SI::meter>(2);
The "2*meters" syntax just seems rather obscure. Likewise, a "measure", a quantity with a specified unit, should be constructed without the need for qualification.
quantity<SI::meter> q (2);
That is, the "2*meters" should not be required when the unit is already explicitly specified as part of the type.
By the way, while meter is an SI unit and therefore belongs in the SI namespace, length is not an SI dimension hence the name "length" does not belong in the SI namespace. It should probably be elevated to the boost::units namespace. I don't believe there is such a thing as an "SI dimension"; i.e. other system of measurement (e.g. Imperial) have units of length as well.
Here's the reasoning for this syntax : quantity<SI::length> represents a quantity of length in the SI system, not a generic length. Because everything is specified at compile time, units and quantities must be completely defined, otherwise it would be impossible to achieve zero runtime overhead. In this usage, meter is, in fact, completely equivalent to SI::length() - it is just a static constant. Another possibility would have been something like this : quantity<SI::meter> q(2*SI::meter()); where SI::meter is now a typedef for the full type representing an SI unit of length (what SI::length is now). Unfortunately, as you add more units, the extraneous parentheses become cumbersome. For example, the definition of the ideal gas constant would go from 8.314*joules/kelvin/mole to 8.314*joules()/kelvin()/mole(). Still legible, but definitely more difficult to follow. Furthermore, in the current syntax, if you had a program that used a bunch of SI units and you wanted to change it to CGS, you could just search and replace SI->CGS and everything would work correctly. If we used the alternative syntax, then a search and replace SI::meter-
CGS::centimeter would do this
quantity<SI::meter> q(2*SI::meters); -> quantity<CGS::centimeter> q (2*CGS::centimeters); which would break the code. Matthias

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Matthias Schabel Sent: Thursday, March 29, 2007 1:56 PM To: boost@lists.boost.org Subject: Re: [boost] units: review
...
Here's the reasoning for this syntax :
quantity<SI::length> represents a quantity of length in the SI system, not a generic length.
Think I understand your rationale now. Your goal is to deal with the scaling problem to accommodate measurements of different magnitudes (e.g. subatomic quantities vs. cosmic quantities)? Not certain this is the best solution but if it works...
Because everything is specified at compile time, units and quantities must be completely defined, otherwise it would be impossible to achieve zero runtime overhead. In this usage, meter is, in fact, completely equivalent to SI::length() - it is just a static constant. Another possibility would have been something like this : quantity<SI::meter> q(2*SI::meter());
Hmm. I still don't understand the rationale for the extra multiplication operation. How is this any different from: quantity<SI::meter> q(2);
Furthermore, in the current syntax, if you had a program that used a bunch of SI units and you wanted to change it to CGS, you could just search and replace
Ack! Search and replace? How about this instead: using namespace CGS; After all, that's the whole point for using namespaces. Eric.

Hmm. I still don't understand the rationale for the extra multiplication operation. How is this any different from:
quantity<SI::meter> q(2);
It's a faux operation - the multiplication of a scalar times a unit (a class with no data members at all) decorates the scalar to produce a quantity of the appropriate unit and value type. The problem with using a raw value type for construction can be demonstrated here : using namespace SI; /// this is two meters quantity<length> q(2); ...some months later... using namespace CGS; /// uh oh - this is 2 centimeters now quantity<length> q(2); The way it's currently implemented, you incur a conversion in the constructor, but the code remains correct if the units are convertible and gives a compile time error if they are not... Matthias

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Matthias Schabel Sent: Thursday, March 29, 2007 2:50 PM To: boost@lists.boost.org Subject: Re: [boost] units: review
You're starting to raise more questions than you're answering. ;)
Hmm. I still don't understand the rationale for the extra multiplication operation. How is this any different from:
quantity<SI::meter> q(2);
It's a faux operation - the multiplication of a scalar times a unit (a class with no data members at all) decorates the scalar to produce a quantity of the appropriate unit and value type. The problem with using a raw value type for construction can be demonstrated here :
It's not a faux operation: the unit is already plainly specified as part of the type and the value of the quantity is plainly specified as the constructor argument. Pretty straight forward if you ask me.
using namespace SI;
/// this is two meters quantity<length> q(2);
First of all, that code should fail to compile. Ignoring the comment, it is (or should be) impossible to construct a quantity with a length of 2. The unit must be specified to the compiler somehow and comments don't count. That is why I distinquished a quantity from a measure in my preview of last year: a quantity is an abstract value that is qualified with one or more dimensions and cannot be constructed directly from arithmetic value. A measure on the other hand accepts a list of units and therefore can be constructed directly from an arithmetic value. A measure can also be converted to a compatible quantity and vice versa. Eric.

Eric Lemings wrote:
It's not a faux operation: the unit is already plainly specified as part of the type and the value of the quantity is plainly specified as the constructor argument. Pretty straight forward if you ask me.
consider this usage: quantity<SI::length> l1(2.0 * SI::meters); quantity<SI::length> l2(2.0 * Astro::parsecs); //for illustration only That's why you need the unit multiplication on the right. This seems to me to be a very clear way to express the fact that you want the quantity to be in the SI length unit (which is the meter), but you want to be free to use whatever units you want to specify it on the right. -Lewis

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Lewis Hyatt Sent: Thursday, March 29, 2007 3:59 PM To: boost@lists.boost.org Subject: Re: [boost] units: review
Eric Lemings wrote:
It's not a faux operation: the unit is already plainly specified as part of the type and the value of the quantity is plainly specified as the constructor argument. Pretty straight forward if you ask me.
consider this usage:
quantity<SI::length> l1(2.0 * SI::meters); quantity<SI::length> l2(2.0 * Astro::parsecs); //for illustration only
I would express that differently: quantity<SI::length> l1 (quantity<SI::meter>(2.0)); quantity<SI::length> l2 (quantity<Astro::parsecs>(2.0)); //for illustration only And I could be way off base here but the latter form would appear more familiar/acceptable to most C++ programmers. Eric.

The former is the way MathCAD does it, and appears more engineeringly correct, imho. Any reason not to support both? Dave -----Original Message----- From: Eric Lemings [mailto:lemings@roguewave.com] Sent: Thursday, March 29, 2007 4:13 PM To: boost@lists.boost.org Subject: Re: [boost] units: review
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Lewis Hyatt Sent: Thursday, March 29, 2007 3:59 PM To: boost@lists.boost.org Subject: Re: [boost] units: review
Eric Lemings wrote:
It's not a faux operation: the unit is already plainly specified as part of the type and the value of the quantity is plainly specified as the constructor argument. Pretty straight forward if you ask me.
consider this usage:
quantity<SI::length> l1(2.0 * SI::meters); quantity<SI::length> l2(2.0
* Astro::parsecs); //for illustration only
I would express that differently: quantity<SI::length> l1 (quantity<SI::meter>(2.0)); quantity<SI::length> l2 (quantity<Astro::parsecs>(2.0)); //for illustration only And I could be way off base here but the latter form would appear more familiar/acceptable to most C++ programmers. Eric. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Eric Lemings wrote:
quantity<SI::length> l1(2.0 * SI::meters); quantity<SI::length> l2(2.0 * Astro::parsecs); //for illustration only
I would express that differently:
quantity<SI::length> l1 (quantity<SI::meter>(2.0)); quantity<SI::length> l2 (quantity<Astro::parsecs>(2.0)); //for illustration only
And I could be way off base here but the latter form would appear more familiar/acceptable to most C++ programmers.
I think it is perfectly natural to think of units as having their own algebra, and so the multiplication notation makes sense. How would you do something like this: quantity<velocity> v(2.0 * meters/second); in your method? I think you'll find that this one is preferable. -Lewis

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Lewis Hyatt Sent: Thursday, March 29, 2007 4:36 PM To: boost@lists.boost.org Subject: Re: [boost] units: review
Eric Lemings wrote:
quantity<SI::length> l1(2.0 * SI::meters); quantity<SI::length> l2(2.0 * Astro::parsecs); //for illustration only
I would express that differently:
quantity<SI::length> l1 (quantity<SI::meter>(2.0)); quantity<SI::length> l2 (quantity<Astro::parsecs>(2.0)); //for illustration only
And I could be way off base here but the latter form would appear more familiar/acceptable to most C++ programmers.
I think it is perfectly natural to think of units as having their own algebra, and so the multiplication notation makes sense. How would you do something like this:
quantity<velocity> v(2.0 * meters/second);
in your method? I think you'll find that this one is preferable.
quantity<velocity> v1 (quantity<meter>(2) / quantity<second>(1)); //or quantity<meter> m(2); quantity<second> s(1); quantity<velocity> v2(m/s); The problem with the "multiplier" usage is it uses a unit name (plural, singular, whatever) for both type information and rvalue expressions. quantity<second[s]> t1 (2.0 * second[s]); This usage may be preferable to scientists and engineers but not C++ programmers, I'll gar-on-tee. Eric.

The problem with the "multiplier" usage is it uses a unit name (plural, singular, whatever) for both type information and rvalue expressions.
quantity<second[s]> t1 (2.0 * second[s]);
This usage may be preferable to scientists and engineers but not C++ programmers, I'll gar-on-tee.
What you wrote doesn't make sense, since seconds is an object, not a type. The point is that the actual syntax is: quantity<SI::time> t1 = 2.0 * SI::seconds; I think this is an important abstraction, that there is a fundamental difference between the physical dimension (time), and the particular units used to measure it (seconds). The syntax makes this clear. The user may be aware that SI::time is represented in seconds in the library internals, but they don't *need* to know this to write dimensionally correct code. (And they will find out eg when they output the value). The fact that SI::seconds is just a static object of type SI::time is not relevant to the fact that "time" and "seconds" have very different meanings. This becomes more clear when you do something like quantity<SI::time> t1 = 2.0 * SI::seconds; quantity<SI::time> t2 = 2.0 * English::fortnights; cout << t1 - t2 << endl; Here, the user doesn't need to worry that t1 and t2 were specified in different units, because they both are quantities of type quantity<SI::time>, so it makes sense to subtract them. The multiplicative syntax seems to me like the most natural choice to handle this usage. As far as I can tell, you seem to be arguing that the usage of "SI::seconds" in the definition of t1 is redundant, because SI::time already implies that the time is measured in seconds, but that's not really the spirit of what a quantity<> is. A quantity<> doesn't represent something in a particular set of units (such as seconds), but rather something that measures a particular physical dimension (such as time). The fact that the quantity<> internally has to choose a unit to represent that dimension is not as important as the fact that the quantity<> does fundamentally represent a physical dimension. Anyway, that's just my interpretation of how this library design works, and IMHO I think it is a good, logical design. -Lewis

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Lewis Hyatt Sent: Friday, March 30, 2007 4:01 PM To: boost@lists.boost.org Subject: Re: [boost] units: review
...
Anyway, that's just my interpretation of how this library design works, and IMHO I think it is a good, logical design.
'2.0 * pi' is a logical expression. '2.0 * seconds' is not and I can't imagine how anyone can think such an expression is "good design". Eric.

On 3/30/07, Eric Lemings <lemings@roguewave.com> wrote:
'2.0 * pi' is a logical expression. '2.0 * seconds' is not and I can't imagine how anyone can think such an expression is "good design".
I think that it's the most readable of the options. It's not going to be possible to have '2.0 seconds' work, so it's reasonable. Just like prefixed Kleene Stars in Spirit, it's the closest to the DSL that can be done. And the mathematical meaning of adjacency is multiplication, so the * is a good choice. It also makes the most sense in conjunction with /, which is going to be there. What do *you* think would be "good design"? It seems to me as though the most straight-forward alternative, 'metre(9.8) / second(1) / second(1)' is much uglier than '9.8 * metres / (second*second)' for no apparent gain. ~ Scott McMurray

On Mar 30, 2007, at 5:59 PM, me22 wrote:
... second(1)' is much uglier than '9.8 * metres / (second*second)' for no apparent gain.
If '9.8 * metres / (second*second)' is a valid expression, then 'metres/(second*second)' must also be a valid expression. What is the result of the latter? Eric.

On 3/31/07, Eric Lemings <eric.lemings@roguewave.com> wrote:
On Mar 30, 2007, at 5:59 PM, me22 wrote:
... second(1)' is much uglier than '9.8 * metres / (second*second)' for no apparent gain.
If '9.8 * metres / (second*second)' is a valid expression, then 'metres/(second*second)' must also be a valid expression. What is the result of the latter?
Is it a legal expression? It's plausible that it doesn't know the desired representation type (double, float, etc). Assuming it is, however, it must be the multiplicative identity: 1 * metres/(second*second) On 3/31/07, Paul A Bristow <pbristow@hetp.u-net.com> wrote:
Ideally we'd have more 'squiggles' for more operators, but the ASCII char set doesn't permit this - C++ has used them all already.
Well, there's still @, $, and `, no? Not that any of those would be better ;) ~ Scott McMurray

second(1)' is much uglier than '9.8 * metres / (second*second)' for no apparent gain.
If '9.8 * metres / (second*second)' is a valid expression, then 'metres/(second*second)' must also be a valid expression. What is the result of the latter?
Is it a legal expression? It's plausible that it doesn't know the desired representation type (double, float, etc).
meters/(second*second) == unit<acceleration_type,SI::system>() Matthias

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Eric Lemings Sent: 31 March 2007 00:27 To: boost@lists.boost.org Subject: Re: [boost] units: review
'2.0 * pi' is a logical expression. '2.0 * seconds' is not and I can't imagine how anyone can think such an expression is "good design".
Ideally we'd have more 'squiggles' for more operators, but the ASCII char set doesn't permit this - C++ has used them all already. Blame it all on paper tape ;-) Paul --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Paul A Bristow Sent: Thursday, March 29, 2007 11:24 AM To: boost@lists.boost.org Subject: Re: [boost] units: review
...
The SI rule for pluralising units is that symbols of units are not pluralised[2], for example "25 kg" (not "25 kgs").
JMHO but that rule should really only apply to I/O of units and measures. I don't think it should necessarily apply to source code as well. Eric.

AMDG Matthias Schabel <boost <at> schabel-family.org> writes:
As I recall, SI specifically says do NOT use the plurals.
I'm not strongly attached to having plurals
I don't particularly care either way. The only issue is that we need pascals because windef.h has #define pascal __stdcall In Christ, Steven Watanabe

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe Sent: 29 March 2007 18:37 To: boost@lists.boost.org Subject: Re: [boost] units: review
AMDG
Matthias Schabel <boost <at> schabel-family.org> writes:
As I recall, SI specifically says do NOT use the plurals.
I'm not strongly attached to having plurals
I don't particularly care either way. The only issue is that we need pascals because windef.h has #define pascal __stdcall
Aaargh! Can't we #undef it? And I agree with Matthias's comment that the no plurals rule only applies to programs not output. It does sound yet another thing to get confused about - is it meter or meters? Probably nothing to get over-excited about :-) Paul PS Still studying the docs ;-) --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com

Hi, On 3/29/07, Steven Watanabe <steven@providere-consulting.com> wrote:
AMDG
Matthias Schabel <boost <at> schabel-family.org> writes:
As I recall, SI specifically says do NOT use the plurals.
I'm not strongly attached to having plurals
I don't particularly care either way. The only issue is that we need pascals because windef.h has #define pascal __stdcall
OTOH, Windows SDK has #define max ... and still there is std::max (which can be a pain, admittedly). Regards, Michael

AMDG Michael Walter <michael.walter <at> gmail.com> writes:
I don't particularly care either way. The only issue is that we need pascals because windef.h has #define pascal __stdcall
OTOH, Windows SDK has #define max ... and still there is std::max (which can be a pain, admittedly).
max is a function like macro so the problems can be circumvented. pascal is an object like macro thus the only way to avoid problems is to undef it ( possibly breaking code in windows) In Christ, Steven Watanabe

AMDG Lewis Hyatt <lhyatt <at> princeton.edu> writes:
-What is your evaluation of the design?
I do disagree with previous comments on the evilness of the mutating value() method.
<snip>
We were going to replace it with quantity_reinterpret_cast<T&>(q). This make the fact that it is dangerous more obvious in addition to allowing searches.
Also, quantity<> should pass through operator++ and operator-- in addition to the other arithmetic operators.
Will do.
<snip>
I was surprised by the following behavior:
#include <iostream> #include <boost/units/io.hpp> #include <boost/units/systems/si.hpp> #include <boost/units/systems/cgs.hpp> #include <boost/units/systems/si/prefixes.hpp> using namespace boost::units;
int main() {
quantity<CGS::force> F0 = 20 * CGS::dyne;
quantity<SI::force> F1 = quantity_cast<SI::force>(F0); quantity<SI::force> F2 = quantity_cast<SI::force>(20 * CGS::dyne);
quantity<SI::force> F3(F0); //quantity<SI::force> F4 = F0;
This requires a conversion. The construtor is explicit.
//quantity<SI::force> F5(20 * CGS::dyne);
Ouch. I noticed this before but never fixed it. I'll take care of it immidiately
//quantity<SI::force> F6 = 20 * CGS::dyne;
Again, the constructor is explicit.
<snip>
Also problematic is F2, which does compile, albeit with a warning, but then does the wrong thing at run time. The output of this program is:
1e-05 m kg s^(-2) 0 m kg s^(-2) 1e-05 m kg s^(-2)
This appears to be related to the fact that in the initialization of F0, there is an implicit conversion from the int (20) to double.
<snip>
I'll fix it.
-What is your evaluation of the documentation?
The large number of examples is excellent. The documentation needs a lot more substance to it, particularly explaining surprising features of implicit conversions.
Better: fix the problems.
-What is your evaluation of the potential usefulness of the library?
One concern I have, is that I use a lot of C++ wrappers over legacy C libraries such as CLAPACK and ATLAS.
<snip>
If you are doing that I would put the assertion at the point where you cast.
<snip>
Thank you. In Christ, Steven Watanabe

Steven Watanabe wrote:
One concern I have, is that I use a lot of C++ wrappers over legacy C libraries such as CLAPACK and ATLAS.
<snip>
If you are doing that I would put the assertion at the point where you cast.
The only problem with that is it would require a separate check for all different types of units in use, even though each check was conceptually doing the same thing. I guess it would be a simple matter for the user to derive a new template from quanity<Q,T> for the sole purpose of adding the static assert, so perhaps the library itself doesn't need to be concerned with this. -Lewis

AMDG Lewis Hyatt <lhyatt <at> princeton.edu> writes:
The only problem with that is it would require a separate check for all different types of units in use, even though each check was conceptually doing the same thing.
I guess it would be a simple matter for the user to derive a new template from quanity<Q,T> for the sole purpose of adding the static assert, so perhaps the library itself doesn't need to be concerned with this.
How about: template<class T, class Unit, class Y> T technically_nonportable_quantity_cast(quantity<Unit, Y>& q) { BOOST_STATIC_ASSERT(sizeof(quantity<Unit, Y>) == sizeof(T)); return(reinterpret_cast<T>(q)); } template<class T, class Unit, class Y> T technically_nonportable_quantity_cast(quantity<Unit, Y>* q) { return(&technically_nonportable_quantity_cast< typename boost::remove_pointer<T>::type& >(*q)); } //overloads for const quantity In Christ, Steven Watanabe

Lewis Hyatt <lhyatt <at> princeton.edu> writes:
Also problematic is F2, which does compile, albeit with a warning, but then does the wrong thing at run time. The output of this program is:
1e-05 m kg s^(-2) 0 m kg s^(-2) 1e-05 m kg s^(-2)
Mathias, for this reason quantity_cast should be quantity_cast<quantity<SI::force> >(q) Agreed? In Christ, Steven Watanabe

Mathias, for this reason quantity_cast should be
quantity_cast<quantity<SI::force> >(q)
Agreed?
I'm actually wondering if we can completely eliminate quantity_cast - with the new quantity_reinterpret_cast and the new conversions including value type, it seems like it is redundant. If so, I'd rather just get rid of it... Matthias

Matthias Schabel <boost <at> schabel-family.org> writes:
Mathias, for this reason quantity_cast should be
quantity_cast<quantity<SI::force> >(q)
Agreed?
I'm actually wondering if we can completely eliminate quantity_cast - with the new quantity_reinterpret_cast and the new conversions including value type, it seems like it is redundant. If so, I'd rather just get rid of it...
I actually prefer to use quantity_cast instead of quantity_reinterpret_cast. After all, the behavior of reinterpret_cast is unspecified except that certain conversions are reversible, while quantity_reinterpret_cast is always well-defined. In Christ, Steven Watanabe

On 3/29/07, Steven Watanabe <steven@providere-consulting.com> wrote:
Matthias Schabel <boost <at> schabel-family.org> writes:
Mathias, for this reason quantity_cast should be
quantity_cast<quantity<SI::force> >(q)
Agreed?
I'm actually wondering if we can completely eliminate quantity_cast - with the new quantity_reinterpret_cast and the new conversions including value type, it seems like it is redundant. If so, I'd rather just get rid of it...
I think it's important to be able to differentiate between conversions that are typesafe (quantity_cast) and those that are not (quantity_reinterpret_cast).
I actually prefer to use quantity_cast instead of quantity_reinterpret_cast. After all, the behavior of reinterpret_cast is unspecified except that certain conversions are reversible, while quantity_reinterpret_cast is always well-defined.
While quantity_reinterpret_cast may not be perfectly analogous to reinterpret_cast, it represents the reinterpretation of a raw number as being of a different type, and so I think it's a pretty good name. Just as importantly, I can't think of anything better. Do you have any other ideas? quantity_unsafe_cast? quantity_arbitrary_cast? :) Zach Laine

While quantity_reinterpret_cast may not be perfectly analogous to reinterpret_cast, it represents the reinterpretation of a raw number as being of a different type, and so I think it's a pretty good name. Just as importantly, I can't think of anything better. Do you have any other ideas? quantity_unsafe_cast? quantity_arbitrary_cast? :)
Sorry, I think I muddied the waters here - I agree that quantity_reinterpret_cast should be reserved for those cases where access to the raw data is necessary. I was just saying that we can write things like quantity<SI::length,double> q; quantity<SI::length,int> r; quantity<CGS::length,double> s; quantity<CGS::length,int> t; q = quantity<SI::length,double>(r); q = quantity<SI::length,double>(s); q = quantity<SI::length,double>(t); already, so the only non-degenerate use case of quantity_cast is to take a raw value and return a quantity: q = quantity_cast< quantity<SI::length,double> >(1.5); Matthias

Matthias Schabel wrote:
While quantity_reinterpret_cast may not be perfectly analogous to reinterpret_cast, it represents the reinterpretation of a raw number as being of a different type, and so I think it's a pretty good name. Just as importantly, I can't think of anything better. Do you have any other ideas? quantity_unsafe_cast? quantity_arbitrary_cast? :)
Sorry, I think I muddied the waters here - I agree that quantity_reinterpret_cast should be reserved for those cases where access to the raw data is necessary. I was just saying that we can write things like
quantity<SI::length,double> q; quantity<SI::length,int> r; quantity<CGS::length,double> s; quantity<CGS::length,int> t;
q = quantity<SI::length,double>(r); q = quantity<SI::length,double>(s); q = quantity<SI::length,double>(t);
already, so the only non-degenerate use case of quantity_cast is to take a raw value and return a quantity:
q = quantity_cast< quantity<SI::length,double> >(1.5);
I think you are right that quantity_cast becomes unnecessary, and in the last usage there, the user should have to specify the units or use quantity_reinterpret_cast. One more thought, instead of: q = quantity<SI::length,double>(r); what about a syntax like q.convert_from(r) to emphasize that this is performing a safe unit conversion, and to avoid having to repeat the type name? -lewis

One more thought, instead of:
q = quantity<SI::length,double>(r);
what about a syntax like
q.convert_from(r)
to emphasize that this is performing a safe unit conversion, and to avoid having to repeat the type name?
We currently have a static member function that works like that : q = quantity<SI::length,double>::from_value(r); Maybe that's enough... Matthias

what about a syntax like
q.convert_from(r)
to emphasize that this is performing a safe unit conversion, and to avoid having to repeat the type name?
We currently have a static member function that works like that :
q = quantity<SI::length,double>::from_value(r);
Maybe that's enough...
It certainly gets the job done, I personally would prefer the other way because q already has a known assigned type, and it is somewhat annoying to have to write it out again just to assign a new value, but it's not such an important point. -Lewis

On 3/29/07, Matthias Schabel <boost@schabel-family.org> wrote:
While quantity_reinterpret_cast may not be perfectly analogous to reinterpret_cast, it represents the reinterpretation of a raw number as being of a different type, and so I think it's a pretty good name. Just as importantly, I can't think of anything better. Do you have any other ideas? quantity_unsafe_cast? quantity_arbitrary_cast? :)
Sorry, I think I muddied the waters here - I agree that quantity_reinterpret_cast should be reserved for those cases where access to the raw data is necessary. I was just saying that we can write things like
quantity<SI::length,double> q; quantity<SI::length,int> r; quantity<CGS::length,double> s; quantity<CGS::length,int> t;
q = quantity<SI::length,double>(r); q = quantity<SI::length,double>(s); q = quantity<SI::length,double>(t);
already, so the only non-degenerate use case of quantity_cast is to take a raw value and return a quantity:
q = quantity_cast< quantity<SI::length,double> >(1.5);
Maybe I'm missing something here, but why shouldn't this last cast be done using a constructor instead: q = quantity<SI::length,double>(1.5*meter); This way, the set of library capabilities is no different, but the resulting code is more explicit, and quantity_cast cannot be used in a type-unsafe way. Further, it's name suggests that quantity_cast only casts between quantities, not between underlying values and quantites. Taking a raw value and constructing a quantity from it should be the sole purview of the quantity constructor. Zach Laine

already, so the only non-degenerate use case of quantity_cast is to take a raw value and return a quantity:
q = quantity_cast< quantity<SI::length,double> >(1.5);
Maybe I'm missing something here, but why shouldn't this last cast be done using a constructor instead:
q = quantity<SI::length,double>(1.5*meter);
This way, the set of library capabilities is no different, but the resulting code is more explicit, and quantity_cast cannot be used in a type-unsafe way. Further, it's name suggests that quantity_cast only casts between quantities, not between underlying values and quantites. Taking a raw value and constructing a quantity from it should be the sole purview of the quantity constructor.
Yes, that would be my preference. We intentionally made the constructors require that everything be explicitly specified or convertible, so direct construction from a bare value type is forbidden - I believe that you agree that this is important. We do need to be able to make end-runs somehow for reasons that have been elucidated already : 1) accessing a non-const reference to the quantity data member this is going to be done through quantity_reinterpret_cast<> 2) construction of a quantity from a bare value type this is done through the static member function quantity<>::from_value (val) 3) getting a const value type reference this is done through the non-mutating value() member function 4) safe conversion of units from one system to another or from one value type to another this is done through the explicit constructor unless implicit conversion has been specifically enabled, either through BOOST_UNITS_ALLOW_IMPLICIT_CONVERSIONS or by enabling specific implicit conversions. I don't think we need any of the quantity_cast variants anymore, but am happy to be corrected... Matthias

On 3/29/07, Matthias Schabel <boost@schabel-family.org> wrote:
already, so the only non-degenerate use case of quantity_cast is to take a raw value and return a quantity:
q = quantity_cast< quantity<SI::length,double> >(1.5);
Maybe I'm missing something here, but why shouldn't this last cast be done using a constructor instead:
q = quantity<SI::length,double>(1.5*meter);
This way, the set of library capabilities is no different, but the resulting code is more explicit, and quantity_cast cannot be used in a type-unsafe way. Further, it's name suggests that quantity_cast only casts between quantities, not between underlying values and quantites. Taking a raw value and constructing a quantity from it should be the sole purview of the quantity constructor.
Yes, that would be my preference. We intentionally made the constructors require that everything be explicitly specified or convertible, so direct construction from a bare value type is forbidden - I believe that you agree that this is important. We do need to be able to make end-runs somehow for reasons that have been elucidated already :
1) accessing a non-const reference to the quantity data member
this is going to be done through quantity_reinterpret_cast<>
2) construction of a quantity from a bare value type
this is done through the static member function quantity<>::from_value (val)
3) getting a const value type reference
this is done through the non-mutating value() member function
4) safe conversion of units from one system to another or from one value type to another
this is done through the explicit constructor unless implicit conversion has been specifically enabled, either through BOOST_UNITS_ALLOW_IMPLICIT_CONVERSIONS or by enabling specific implicit conversions.
I don't think we need any of the quantity_cast variants anymore, but am happy to be corrected...
I guess I was missing something. I understand now why you want to get rid of quantity_cast. The above sounds good to me. Zach Laine

AMDG Zach Laine <whatwasthataddress <at> gmail.com> writes:
I don't think we need any of the quantity_cast variants anymore, but am happy to be corrected...
I guess I was missing something. I understand now why you want to get rid of quantity_cast. The above sounds good to me.
Since quantity_cast is no longer being used maybe we should use it instead of quantity_reinterpret_cast? I've already implemented this so I would just need to remove the other specializations. In Christ, Steven Watanabe

On 3/29/07, Steven Watanabe <steven@providere-consulting.com> wrote:
AMDG
Zach Laine <whatwasthataddress <at> gmail.com> writes:
I don't think we need any of the quantity_cast variants anymore, but am happy to be corrected...
I guess I was missing something. I understand now why you want to get rid of quantity_cast. The above sounds good to me.
Since quantity_cast is no longer being used maybe we should use it instead of quantity_reinterpret_cast? I've already implemented this so I would just need to remove the other specializations.
I could certainly live with that, though I'd prefer something that sounds a little more ... dangerous. :) Zach Laine

AMDG Matthias Schabel <boost <at> schabel-family.org> writes:
I could certainly live with that, though I'd prefer something that sounds a little more ... dangerous. :)
I prefer quantity_reinterpret_cast myself - more time to think while you're typing...
I don't think the name matters from a safety perspective. How likely is someone to accidently use a cast, especially if it only has a single meaning? Also, extracting the value type is, IMO, safer than static_cast and const_cast because those can produce a value that is incorrect to use at all. In Christ, Steven Watanabe

I prefer quantity_reinterpret_cast myself - more time to think while you're typing...
I don't think the name matters from a safety perspective. How likely is someone to accidently use a cast, especially if it only has a single meaning? Also, extracting the value type is, IMO, safer than static_cast and const_cast because those can produce a value that is incorrect to use at all.
Good point - I'm OK with having a single well-defined quantity_cast, eliminating the other use cases and eliminating quantity_reinterpret_cast - for the latter, users might just as well use the built-in reinterpret_cast... Matthias

Matthias Schabel wrote:
Good point - I'm OK with having a single well-defined quantity_cast, eliminating the other use cases and eliminating quantity_reinterpret_cast - for the latter, users might just as well use the built-in reinterpret_cast...
Matthias
Do the casts give you anything that dividing by the unit doesn't get for you? For example, if we have a quantity len, and we want to get the value: quantity<SI::length> len = 2.0 * SI::meters; double d = len / SI::meters; // <---- gets the value!! David

Do the casts give you anything that dividing by the unit doesn't get for you? For example, if we have a quantity len, and we want to get the value:
quantity<SI::length> len = 2.0 * SI::meters; double d = len / SI::meters; // <---- gets the value!!
We're mainly concerned here about getting a non-const reference to the actual data. In the release version, we will be eliminating the existing quantity_casts as they are redundant and replacing them with one that allows direct mutating access to the underlying value_type... Matthias

Steven, What's going on with the quantity_cast/quantity_reinterpret_cast business - we should decide specifically how this needs to function and what the interface is going to be. I would also prefer to minimize duplication of functionality (Re: my earlier post) as much as possible. Matthias

Lewis, First off, thanks for the thorough review and for pointing out some bugs that have crept in - I'll make sure to add these test cases to the unit tests so they are caught as they should have been.
Also, quantity<> should pass through operator++ and operator-- in addition to the other arithmetic operators.
I debated this for a while - the only problem is that there will be some value types with heterogeneous operator+ / operator- for which q + 1 is not the same type as q, but I guess that it is just OK for it to just give a compile error in those cases.
I was surprised to find that the prefixes kilo, mega, etc, are in namespace SI. They are equally useful for CGS and for user defined systems; perhaps they should be in a new namespace boost::units::prefix, since they are just static constants? Also, I was surprised that units/systems/si/prefixes.hpp was not included by units/systems/ si.hpp, since I thought that was going to be a "catch-all" header.
Good suggestions.
quantity<CGS::force> F0 = 20 * CGS::dyne;
quantity<SI::force> F1 = quantity_cast<SI::force>(F0); quantity<SI::force> F2 = quantity_cast<SI::force>(20 * CGS::dyne);
quantity<SI::force> F3(F0); //quantity<SI::force> F4 = F0;
//quantity<SI::force> F5(20 * CGS::dyne); //quantity<SI::force> F6 = 20 * CGS::dyne;
Firstly, I would have expected all 6 initializations of F1-F6 to do exactly the same thing. The last three do not compile at all, though. I
You've found a couple of bugs that crept in after some rewriting of the code to make it a little more terse. F6 is not expected to convert because implicit unit system conversions are prohibited while explicit unit system conversions are allowed. The other five cases should be identical, as you expect.
The large number of examples is excellent. The documentation needs a lot more substance to it, particularly explaining surprising features of implicit conversions.
The implicit/explicit conversion rules are documented, but, as they can be surprising, should probably be more front and center.
over legacy C libraries such as CLAPACK and ATLAS. I would still be able to use boost::units, provided I could count on sizeof (quantity<Q,T>) == sizeof(T), so that an array of quantitity<Q,T> would look the same in
Unfortunately, I believe that there is no way to guarantee this since quantity isn't a POD type. However, we certainly could put in a compile-time assert on sizeof like you suggest...
The compile of cmath fails on gcc 3.4.4 on cygwin/MinGW and on gcc 3.4.6 on Linux because of undefined symbol __builtin_signbit in detail/cmath_gnu_impl.hpp line 195. This prohibits eg compilation of unit_example_11.cpp
I forgot to skip these cases on MinGW - didn't know that it was a problem under Linux. Maybe I'll just remove the signbit part in the example since the support is spotty anyway.
Yes, I think this library is a good and useful example of compile- time programming, and it should be accepted. I do have some concerns about the implicit conversions and initialization issues, but I think they probably just stem from my lack of understanding of some implementation issues, which means that improved docs would probably suffice to take care of them. I do think the one issue I mentioned above (the combination of quantity_cast and a conversion from int to double producing incorrect runtime behavior) qualifies as a bug, perhaps compiler-specific?
Thanks for your vote and, more importantly, for the close look. We'll fix the bugs ASAP. Matthias

On 3/28/07, Lewis Hyatt <lhyatt@princeton.edu> wrote:
... Also, quantity<> should pass through operator++ and operator-- in addition to the other arithmetic operators.
I strongly disagree. Those operators make no sense for dimensioned quantities; it would be like allowing "12.34 meters + 1". --Ben

Also, quantity<> should pass through operator++ and operator-- in addition to the other arithmetic operators.
I strongly disagree. Those operators make no sense for dimensioned quantities; it would be like allowing "12.34 meters + 1".
This raises an interesting question; in this case double v(1.0); ++v; does the ++v mean v = v + 1; or v = v + double(1); ? In either case, this would be illegal with our current quantity syntax, so perhaps it should not be supported, at least until a clear need for it is demonstrated... Matthias

Ben FrantzDale wrote:
On 3/28/07, Lewis Hyatt <lhyatt@princeton.edu> wrote:
... Also, quantity<> should pass through operator++ and operator-- in addition to the other arithmetic operators.
I strongly disagree. Those operators make no sense for dimensioned quantities; it would be like allowing "12.34 meters + 1".
It is a common idiom that operator++ means "increment by one 'step', in whatever way is appropriate." For instance, boost::progress_timer provides operator++. But no one is confused as to its meaning--it is clear that the increment is perfomed in the natural units of the object (namely, progress ticks) rather than in absolute numbers. In the boost::units case, it makes perfect sense that the increment of a dimensionful quantity is in the appropriate units. For instance: for(quantity<SI::electric_potential> V = 1 * SI::volt; V != 10*SI::volt; ++V) { cout << "voltage is now at " << V << endl; } I think this is perfectly natural, and should compile. Disallowing this will force users of more complex types to create temporary objects in cases where operator++ would render them unnecessary; I think this is too restrictive. -Lewis

for(quantity<SI::electric_potential> V = 1 * SI::volt; V != 10*SI::volt; ++V) { cout << "voltage is now at " << V << endl; }
I think this is perfectly natural, and should compile. Disallowing this will force users of more complex types to create temporary objects in cases where operator++ would render them unnecessary; I think this is too restrictive.
OK, I take it back, this shouldn't be supported. Code like this would be very confusing: for(quantity<SI::electric_potential> V = 1 * SI::kilo * SI::volt; V != 10 * SI::kilo * SI::volt; ++V) cout << V << endl; I guess in that case people might assume the ++ means add 1 kV, instead of 1V. Since the "natural" unit of increase depends on context, and people may not always know what the underlying units system is (eg, is mass in grams or kilograms?), this shouldn't be allowed. -Lewis
participants (12)
-
Ben FrantzDale
-
David Walthall
-
Eric Lemings
-
Eric Lemings
-
Hickerson, David A
-
Lewis Hyatt
-
Matthias Schabel
-
me22
-
Michael Walter
-
Paul A Bristow
-
Steven Watanabe
-
Zach Laine