
Greetings, I have been working on a rather ambitious dimensional analysis framework and units of measurement library suitable for inclusion with the Boost libraries. The interface is probably quite different from anything previously seen but hopefully it is more intuitive, flexible, and...well...appealing. The design and implementation are still in flux but most of the functionality is in place. Several Boost developers have advised me to post it here to solicit comments and feedback. The "preview" release can be found in the Units folder of the Boost Vault. The filename is units-preview.zip. Some quick notes. The Tutorial section of the documentation is probably the most important and complete section. The header files contain only some of the most commonly-used units. Plenty more will be be added in the future. I would greatly appreciate questions, comments, and/or suggestions regarding the overall design and interface. I plan to keep working on this library until it is ready for a formal Boost Units library proposal. Thanks, Eric.

Hi Eric, "Eric Lemings" <lemings@roguewave.com> wrote in message news:D730FF7CEDDCA64483F9E99D999A158B41FFD3@qxvcexch01.ad.quovadx.com...
Greetings,
I have been working on a rather ambitious dimensional analysis framework and units of measurement library suitable for inclusion with the Boost libraries. The interface is probably quite different from anything previously seen but hopefully it is more intuitive, flexible, and...well...appealing.
I'm not quite sure which way to take this. Does this mean that you consider the Quan UI unsatisfactory and beyond repair? http://www.sourceforge.net/projects/quan FWIW We have been doing extensive work on Quan, though it is not yet released but the latest code ( on two_param-branch in CVS) is now stable and tested on VC7.1 and gcc4.0 . In the next release the major change is a move from having three template parameters in the fixed_quantity to just two. These consist of a Concept named StaticUnit and another called NumericType. The signature now looks like this: quan::fixed_quantity<StaticUnit,NumericType> . The documentation for the new system is lagging but a Concept checking function for the StaticUnit Concept can be seen here: http://tinyurl.com/g32ew The StaticUnit is opaque and accessed solely via free metafunctions. This allows for a great deal of flexibility in the implementation. As an example a very simple implementaion using an mpl::vector can be seen here: http://tinyurl.com/kbvbq The implementation is loosely based on the dimensional analysis example in David Abrahams and Alexei Gurtovoys TMP book The implementation can be seen here: http://tinyurl.com/e7hch This implementation is of course additional to the default implementation which is much more comprehensive. It would be interesting to try to plug your Boost.Units code in to see if it would work too. The design and implementation are still in flux
but most of the functionality is in place. Several Boost developers have advised me to post it here to solicit comments and feedback.
The "preview" release can be found in the Units folder of the Boost Vault. The filename is units-preview.zip.
Some quick notes. The Tutorial section of the documentation is probably the most important and complete section. The header files contain only some of the most commonly-used units. Plenty more will be be added in the future.
I would greatly appreciate questions, comments, and/or suggestions regarding the overall design and interface. I plan to keep working on this library until it is ready for a formal Boost Units library proposal.
Tested in VC7.1 and VC8.0 of vthe two examples gave compile errors. Testing in gcc 4.0 gave a failed assertion at runtime Is the structure of a unit / conversion factor based on that in quan?. It certainly looks very similar. I will be interested in seeing the updated code, and hopefully to see if it is possible to plug it in to Quan. regards Andy Little

Eric Lemings wrote:
Greetings, Hello
Some quick notes. The Tutorial section of the documentation is probably the most important and complete section. The header files contain only some of the most commonly-used units. Plenty more will be be added in the future. Why do you want to provide plenty of premade units? I though a unit library was supposed to allow the user to construct units in a simple way. It seems very verbose to me to add a new unit.
I think that that what users want is an easy way to define and use their units, not those avaiable in a huge library. So a unit library must in my eyes be very extensible. It must also avoid tying people to any unit system as it depends on the situation which system or sub system is best. Some time ago I also wrote a unit library. It uses an in my eyes very different way to approach the problem so it might be interesting to post the code somewhere. I could upload the code to boost vault so people could comment on its design. Where should I put it so that people don't confuse both libraies.

Ben Strasser wrote:
Why do you want to provide plenty of premade units? I though a unit library was supposed to allow the user to construct units in a simple way. It seems very verbose to me to add a new unit.
There are two distinct visions of what a units/dimensions library should be. So far, those who are willing to put the work into submitting a library into boost fall into the prebuilty SI units camp.
I think that that what users want is an easy way to define and use their units, not those avaiable in a huge library. So a unit library must in my eyes be very extensible. It must also avoid tying people to any unit system as it depends on the situation which system or sub system is best.
This is what a few of us also want.
Some time ago I also wrote a unit library. It uses an in my eyes very different way to approach the problem so it might be interesting to post the code somewhere. I could upload the code to boost vault so people could comment on its design. Where should I put it so that people don't confuse both libraies.
Please do. Deane

"Ben Strasser" <strasser.ben@googlemail.com> wrote in message news:loom.20060827T232339-182@post.gmane.org...
Eric Lemings wrote:
Greetings, Hello
Some quick notes. The Tutorial section of the documentation is probably the most important and complete section. The header files contain only some of the most commonly-used units. Plenty more will be be added in the future. Why do you want to provide plenty of premade units? I though a unit library was supposed to allow the user to construct units in a simple way.
FWIW The situation where everybody makes up their own units is pretty much the reason why the SI was set up.
I think that that what users want is an easy way to define and use their units, not those avaiable in a huge library. So a unit library must in my eyes be very extensible. It must also avoid tying people to any unit system as it depends on the situation which system or sub system is best.
Some time ago I also wrote a unit library. It uses an in my eyes very different way to approach the problem so it might be interesting to post the code somewhere. I could upload the code to boost vault so people could comment on its design. Where should I put it so that people don't confuse both libraies.
Just put it somewhere in the Boost vault, and then post the list where it is. I would be interested to see a different approach too. regards Andy Little

I uploaded the into the boost vault. It's in the units directory and has the name alternative_units.zip

"Ben Strasser" <strasser.ben@googlemail.com> wrote in message news:loom.20060828T152134-716@post.gmane.org...
I uploaded the into the boost vault. It's in the units directory and has the name alternative_units.zip
Hi Ben, I took a look at the library. I liked the idea of being able to define a runtime evaluable conversion factor, though in Quan: http://sourceforge.net/projects/quan/ I guess we would make that a separate class. I liked the example in basic.cpp. It compiled and ran OK in gcc4.0 but unfortunately not in VC7.1. Overall the library needs needs to be fleshed out much more though IMO. However I disagree that users like to spend time making their own units. Quan has a fair number of units supplied(still nowhere near enough though) and when they are available they are very much more convenient to use. Also I/O is useful. I looked at how I would do the basic.cpp example in Quan. Note that the units output comes in very handy here and also note the use of the predefined units, which saves a lot of time and effort creating units. regards Andy Little // Copyright Andrew Little, Ben Strasser 2006 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See QUAN_ROOT/quan_matters/index.html for documentation. /* Example inspired by basic.cpp in alternative units which is: // Copyright 2006 Ben Strasser. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) */ #include <quan/out/mass.hpp> #include <quan/out/length.hpp> #include <quan/out/time.hpp> #include <quan/out/energy.hpp> #include <boost/shared_ptr.hpp> #include <string> #include <map> // map quantities in various units // to a target quantity via their output unit string // use that to look up the conversion routine template <typename TargetQuan> class quantity_map{ // abstract base class for converting // to target fixed_quantity type struct abc_converter{ virtual TargetQuan convert(double val)const=0; ~abc_converter(){} }; // implementation of the unit converter template <typename SourceQuan> struct converter : abc_converter{ BOOST_MPL_ASSERT((boost::is_convertible<SourceQuan,TargetQuan>)); TargetQuan convert(double val)const { return SourceQuan(val); } }; public: typedef boost::shared_ptr<abc_converter> quantity_ptr; std::map<std::string,quantity_ptr> m_map; template <typename SourceQuan> void add_unit() { BOOST_MPL_ASSERT((boost::is_convertible<SourceQuan,TargetQuan>)); m_map [units_str(SourceQuan())] = quantity_ptr(new converter<SourceQuan>); } bool find (std::string const & str)const { return m_map.find(str) != m_map.end(); } }; int main() { // fill the maps with units as required quantity_map<quan::mass::kg> mass_map; mass_map.add_unit<quan::mass::kg>(); mass_map.add_unit<quan::mass::lb>(); quantity_map<quan::time::s> time_map; time_map.add_unit<quan::time::s>(); time_map.add_unit<quan::time::min>(); time_map.add_unit<quan::time::h>(); quantity_map<quan::length::m> length_map; length_map.add_unit<quan::length::m>(); length_map.add_unit<quan::length::mi>(); length_map.add_unit<quan::length::yd>(); length_map.add_unit<quan::length::km>(); // calculation input variables quan::mass::kg my_mass; quan::time::s my_time; quan::length::m my_distance; // user input variables std::string str; double val; while (1){ std::cout << "How much do you weigh (specify lb or kg)? : "; std::cin >> val >> str; if ( ! mass_map.find(str)){ std::cout << "Unfortunately " << str << " units arent supported. Try another unit\n"; continue; } else { my_mass = mass_map.m_map[str]->convert(val); break; } } while (1){ std::cout << "How far did you walk (specify m, mi, yd, km)? : "; std::cin >> val >> str; if ( ! length_map.find(str)){ std::cout << "Unfortunately " << str << " units arent supported. Try another unit\n"; continue; } else { my_distance = length_map.m_map[str]->convert(val); break; } } while (1){ std::cout << "How long did you take? (specify min, s, h)? : "; std::cin >> val >> str; if ( ! time_map.find(str)){ std::cout << "Unfortunately " << str << " units arent supported. Try another unit\n"; continue; } else { my_time = time_map.m_map[str]->convert(val); break; } } quan::energy::J my_energy = my_mass * quan::pow<2>(my_distance / my_time); std::cout << "Your kinetic energy was : " << my_energy << '\n'; } /* sample output: How much do you weigh (specify lb or kg)? : 150 lb How far did you walk (specify m, mi, yd, km)? : 20 mi How long did you take? (specify min, s, h)? : 4 h Your kinetic energy was : 339.93 J */

I've taken a quick look at the documentation of Ben's units library and tried to compile it using VC++ 8.0. Andy Little wrote:
I liked the example in basic.cpp. It compiled and ran OK in gcc4.0 but unfortunately not in VC7.1.
I was unable to get it to compile in VC8.0. It gives errors in the compile-time rational number code (in compile_time_number.hpp).
Overall the library needs needs to be fleshed out much more though IMO.
Not for me. It looks very close to what I want. The only thing I would like to see is a preferred implementation for explicit conversion between different units of the same dimension. I could probably add this layer to the library myself but was wondering if you've done this already.
However I disagree that users like to spend time making their own units.
I disagree with Andy's disagreement. Only physicists working with all of the physical dimensions would find it more convenient to have a library with lots of dimensions and units prebuilt. For most applications (it seems to be very hard to convince the physicists that a units library has applications outside of physics), a more lightweight library is all that's needed.
Also I/O is useful.
Built-in I/O is more important when the library comes with a lot of built-in dimensions and units. It's much less important when the library does not. Deane

Deane Yang <deane_yang <at> yahoo.com> writes:
I've taken a quick look at the documentation of Ben's units library and tried to compile it using VC++ 8.0.
Andy Little wrote:
I liked the example in basic.cpp. It compiled and ran OK in gcc4.0 but unfortunately not in VC7.1.
I was unable to get it to compile in VC8.0. It gives errors in the compile-time rational number code (in compile_time_number.hpp).
Could you please post the error message? I only tested it on the lastest mingw.
It looks very close to what I want. The only thing I would like to see is a preferred implementation for explicit conversion between different units of the same dimension. I could probably add this layer to the library myself but was wondering if you've done this already. You mean disallowing implicit conversion? Look at the currency.cpp example. It's a mixure of implicit static conversions (cent <-> euro) and of explicit dynamic conversions (euro <-> dollar <-> yen). An implicit conversion between euro and dollar is not possible.

Ben Strasser wrote:
Deane Yang <deane_yang <at> yahoo.com> writes:
I was unable to get it to compile in VC8.0. It gives errors in the compile-time rational number code (in compile_time_number.hpp).
Could you please post the error message? I only tested it on the lastest mingw.
c:\home\deane\svn\software\vendor\alternative_units\include\units\compile_time_number.hpp(53) : error C2057: expected constant expression c:\home\deane\svn\software\vendor\alternative_units\include\units\compile_time_number.hpp(94) : see reference to class template instantiation 'compile_time_number::reduce<n>' being compiled with [ n=compile_time_number::rational<1> ] c:\home\deane\svn\software\vendor\alternative_units\include\units\quantity.hpp(253) : see reference to class template instantiation 'compile_time_number::multiply<n1,n2>' being compiled with [ n1=compile_time_number::rational<1>, n2=compile_time_number::rational<1> ] c:\home\deane\svn\software\vendor\alternative_units\include\units\quantity.hpp(296) : see reference to class template instantiation 'units::raise_to<Tlist,Tnum>' being compiled with [ Tlist=mass, Tnum=compile_time_number::rational<1> ] c:\home\deane\svn\software\vendor\alternative_units\include\units\quantity.hpp(310) : see reference to class template instantiation 'units::irrational_quantity<Q,P,Q0,P0,Q1,P1,Q2,P2,Q3,P3,Q4,P4>' being compiled with [ Q=acceleration, P=compile_time_number::rational<1>, Q0=mass, P0=compile_time_number::rational<1>, Q1=length, P1=compile_time_number::rational<1>, Q2=units::no_quantity, P2=compile_time_number::rational<1>, Q3=units::no_quantity, P3=compile_time_number::rational<1>, Q4=units::no_quantity, P4=compile_time_number::rational<1> ] c:\home\deane\svn\software\vendor\alternative_units\include\units\quantity.hpp(37) : see reference to class template instantiation 'units::quantity<Q,P,Q0,P0,Q1,P1>' being compiled with [ Q=acceleration, P=1, Q0=mass, P0=1, Q1=length, P1=1 ] include\units/unit.hpp(34) : see reference to class template instantiation 'units::detail::is_end<Tquan>' being compiled with [ Tquan=energie ] example\basic.cpp(40) : see reference to class template instantiation 'units::unit<Tquan>' being compiled with [ Tquan=energie ] c:\home\deane\svn\software\vendor\alternative_units\include\units\compile_time_number.hpp(58) : error C2975: 'Tnum' : invalid template argument for 'compile_time_number::rational', expected compile-time constant expression c:\home\deane\svn\software\vendor\alternative_units\include\units\compile_time_number.hpp(40) : see declaration of 'Tnum' c:\home\deane\svn\software\vendor\alternative_units\include\units\compile_time_number.hpp(58) : error C2975: 'Tdenom' : invalid template argument for 'compile_time_number::rational', expected compile-time constant expression c:\home\deane\svn\software\vendor\alternative_units\include\units\compile_time_number.hpp(40) : see declaration of 'Tdenom' c:\home\deane\svn\software\vendor\alternative_units\include\units\compile_time_number.hpp(67) : fatal error C1903: unable to recover from previous error(s); stopping compilation c:\home\deane\svn\software\vendor\alternative_units\include\units\quantity.hpp(111) : see reference to class template instantiation 'compile_time_number::add<n1,n2>' being compiled with [ n1=compile_time_number::rational<0>, n2=compile_time_number::rational<0,0> ] c:\home\deane\svn\software\vendor\alternative_units\include\units\quantity.hpp(120) : see reference to class template instantiation 'units::detail::insert_into_list_internal<Tlist,Tquan,Tpow,Tcombiner>' being compiled with [ Tlist=units::detail::quan_list_end, Tquan=mass, Tpow=compile_time_number::rational<0,0>, Tcombiner=compile_time_number::add ] c:\home\deane\svn\software\vendor\alternative_units\include\units\quantity.hpp(138) : see reference to class template instantiation 'units::detail::insert_into_list<Tlist,Tquan,Tpow,Tcombiner>' being compiled with [ Tlist=units::detail::quan_list_end, Tquan=mass, Tpow=compile_time_number::rational<0,0>, Tcombiner=compile_time_number::add ] c:\home\deane\svn\software\vendor\alternative_units\include\units\quantity.hpp(238) : see reference to class template instantiation 'units::combine<Tlist1,Tlist2,Tcombiner>' being compiled with [ Tlist1=units::detail::quan_list_end, Tlist2=units::detail::quan_node<units::raise_to<units::detail::quan_list_end,compile_time_number::rational<1>,compile_time_number::multiply>::type,mass,compile_time_number::rational<0,0>>, Tcombiner=compile_time_number::add ] c:\home\deane\svn\software\vendor\alternative_units\include\units\quantity.hpp(296) : see reference to class template instantiation 'units::combine_by_multiplication<Tlist1,Tlist2>' being compiled with [ Tlist1=units::detail::quan_list_end, Tlist2=units::detail::quan_node<units::raise_to<units::detail::quan_list_end,compile_time_number::rational<1>,compile_time_number::multiply>::type,mass,compile_time_number::rational<0,0>> ]

However I disagree that users like to spend time making their own units. Quan has a fair number of units supplied(still nowhere near enough though) and when they are available they are very much more convenient to use. Also I/O is useful. The original idea for this library was based on a real world example that you certainly can't have in your library.
Consider a function grapher with a GUI and a scollable view of the graph. How many different types of vectors (=points) do you have? There is "mathematical" vector, meaning the solutions of the equations. Then there are those in virtual screen coordinates, meaning a scroll undepand pixel fixed version. The relation between "mathematical" vectors and virtual ones varies with the display setting of the user so you can't hard code the realtions. And there are the scroll relative vectors or also client area vectors. These are the 3 I though of when designing the app. Later I dicoverd 2 new ones : The scroll position and window relative coordinates. You could also add screen relative if you want to. I doubt that you can provide a simple to use interface to differenciate these 6 units of vectors. Another example would be games with an isometric grid. You will spend a lot of time mapping vectors from grid coordinates to screen coordinates and back. However you do have a point that it might be better to provide stock types. For example the length quantity. It would make inoperation of code more easily. An alternative would be to provide a sort of quantity cast that allows to bypass the type check mechanism at junction points. The first option sounds better but the later is in my eyes more realisitc as you will always forget at least one quantity.
I looked at how I would do the basic.cpp example in Quan. Note that the units output comes in very handy here and also note the use of the predefined units, which saves a lot of time and effort creating units.
The basic example is also meant to be elementary so you can implement it obviously better with elementary stock types. However how often do you calculate the cinetique energie in real world examples? About the unit I/O : I've though about providing a mechanism for it but decided later to drop it. The reason is that it adds nothing the user couldn't already do just as simply. To provide output you need a symbol. This means that you need additional arguments to your units because you can not default generate one. As strings are very bad template arguments this will add at least one line of code. However in that case the user could also simply have written ostream&operator<<(ostream&out, meter n){return out<<n.raw()<<"m";} and he has the output exactly the way he wants. No problems with unicode or the symbol not being just the way the user wants it. For the input you need a list of all inputable units, symbol position, raw number formats and symbols. In the best case this would be a long template argument list that reminds an if else chain. So why not simply use an if else chain like in the unit_converter.cpp example?

...dropping out of lurk mode for one comment...keeping in mind that I have not looked at the library or read a big chunk of this thread...
About the unit I/O : I've though about providing a mechanism for it but decided later to drop it. The reason is that it adds nothing the user couldn't already do just as simply.
To provide output you need a symbol. This means that you need additional arguments to your units because you can not default generate one. As strings are very bad template arguments this will add at least one line of code. However in that case the user could also simply have written
ostream&operator<<(ostream&out, meter n){return out<<n.raw()<<"m";}
and he has the output exactly the way he wants. No problems with unicode or the symbol not being just the way the user wants it.
For the input you need a list of all inputable units, symbol position, raw number formats and symbols. In the best case this would be a long template argument list that reminds an if else chain. So why not simply use an if else chain like in the unit_converter.cpp example?
I/O turns out to be something that is quite difficult to do well. There's plenty of issues like: support for wide streams, support for different domain contexts (eg: sometimes I want it to be 'm' and sometimes 'meters'), internationalization of number format, support for serialization. In date-time, there's probably more effort in I/O than any other single aspect of the library. For me, a units library that doesn't seriously address I/O doesn't really finish the job of providing a set of types for application programmers that don't require major extension to use correctly. The whole point of this should be that I can put a 'unit type' in place of an double or some native type. If I have to write an ostream operator to use the library it doesn't make it as a 'double replacement'. ...back to lurk mode... Jeff

Jeff Garland wrote:
...dropping out of lurk mode for one comment...keeping in mind that I have not looked at the library or read a big chunk of this thread...
I/O turns out to be something that is quite difficult to do well. There's plenty of issues like: support for wide streams, support for different domain contexts (eg: sometimes I want it to be 'm' and sometimes 'meters'), internationalization of number format, support for serialization. In date-time, there's probably more effort in I/O than any other single aspect of the library.
Um, just a thought... can we have a flag for Commonwealth/US spellings, so that the user can choose whether to have "metres" and "litres" or "meters" and "liters", rather than just assuming every speaks US English (_pace_ our American cousins)? Here, "meters" are used for measuring all sorts of things, but not length, and are also those things you put coins in when you park... Recall that allowing the spellings "meter" and "liter" was a concession made to the US (and some other countries where this spelling is used), and so this spelling is a permitted variant, not the standard spelling. Likewise for "deca-" versus "deka-", should this prefix be part of the library. Perhaps this can be done as part of the L10n of the library. Thanks. Paul

Paul Giaccone wrote:
Jeff Garland wrote:
...dropping out of lurk mode for one comment...keeping in mind that I have not looked at the library or read a big chunk of this thread...
I/O turns out to be something that is quite difficult to do well. There's plenty of issues like: support for wide streams, support for different domain contexts (eg: sometimes I want it to be 'm' and sometimes 'meters'), internationalization of number format, support for serialization. In date-time, there's probably more effort in I/O than any other single aspect of the library.
Um, just a thought... can we have a flag for Commonwealth/US spellings, so that the user can choose whether to have "metres" and "litres" or "meters" and "liters", rather than just assuming every speaks US English (_pace_ our American cousins)? Here, "meters" are used for measuring all sorts of things, but not length, and are also those things you put coins in when you park... Recall that allowing the spellings "meter" and "liter" was a concession made to the US (and some other countries where this spelling is used), and so this spelling is a permitted variant, not the standard spelling. Likewise for "deca-" versus "deka-", should this prefix be part of the library.
Right, that's one aspect I didn't mention. The analogy with date_time is you have to be able to replace all the month names (Jan, Feb, etc) and day of the week strings (Sun, Mon, ...). Basically, the user needs to be able to replace these strings without rewriting the streaming operators. This requires a custom i/o facet and streaming operators that use it. And then you need manipulators to setup the stream to easily select short versus long strings. As I said, it's quite involved and requires more knowledge of i/o streams than most developers aspire to.
Perhaps this can be done as part of the L10n of the library.
I doubt it, the facet interface is tied to the unit types supported by the library. Jeff

Paul Giaccone <paulg <at> cinesite.co.uk> writes:
Um, just a thought... can we have a flag for Commonwealth/US spellings, so that the user can choose whether to have "metres" and "litres" or "meters" and "liters", rather than just assuming every speaks US English (_pace_ our American cousins)? Here, "meters" are used for measuring all sorts of things, but not length, and are also those things you put coins in when you park... Recall that allowing the spellings "meter" and "liter" was a concession made to the US (and some other countries where this spelling is used), and so this spelling is a permitted variant, not the standard spelling. Likewise for "deca-" versus "deka-", should this prefix be part of the library. I intend to make it easy for users to define their units from ground up. This way they have full control over what is happening and aren't forced into notations that aren't their's.

Jeff Garland <jeff <at> crystalclearsoftware.com> writes:
I/O turns out to be something that is quite difficult to do well. There's plenty of issues like: support for wide streams, support for different domain contexts (eg: sometimes I want it to be 'm' and sometimes 'meters'), internationalization of number format, support for serialization. In date-time, there's probably more effort in I/O than any other single aspect of the library. I fully agree with you.
For me, a units library that doesn't seriously address I/O doesn't really finish the job of providing a set of types for application programmers that don't require major extension to use correctly. The whole point of this should be that I can put a 'unit type' in place of an double or some native type. If I have to write an ostream operator to use the library it doesn't make it as a 'double replacement'. I agree with you on this point.
However I hope you do agree with me that everybody uses units a bit differently so it is impossible to provide all possibilities. Even if you supported all existing standards many people will want non standard units. This means that most of the units will have to be user defined. Now let us imagine we could realize every infterface we wanted. How would the interface look like? For simple situations it should be simple and be able to adabte to complex ones. The simplest situation would be to have a non unicode unit postfix. So the ideal interface would look similar to typedef unit<length, "m"> meter; by not providing I/O support we actually get extremly close to this typedef unit<length> meter; ostream&operator<<(ostream&out, meter n){return out<<n.raw()<<"m";} It is indeed a bit verbose but every feasable unit interface is in my eyes more verbose. The only real alternative is a macro that expands to the operator<<. In more complex situations you run accross the problem that you can no longer deduce the correct unit type. This is also the reason why PQU (= Physical Quantities Units) has introduced annomymous units. However in what way does this help? None that I can think of because in both situation (meaning non printable units and annomymous units) the users has to indicate how to print the units. The conclusion that I come to is there is nothing that even an ideal interface could provide that isn't already just as simply possible with the interface the iostreams provide for every type. All you can do is making things more complicated.

Ben Strasser wrote:
Jeff Garland <jeff <at> crystalclearsoftware.com> writes:
I/O turns out to be something that is quite difficult to do well. There's plenty of issues like: support for wide streams, support for different domain contexts (eg: sometimes I want it to be 'm' and sometimes 'meters'), internationalization of number format, support for serialization. In date-time, there's probably more effort in I/O than any other single aspect of the library. I fully agree with you.
For me, a units library that doesn't seriously address I/O doesn't really finish the job of providing a set of types for application programmers that don't require major extension to use correctly. The whole point of this should be that I can put a 'unit type' in place of an double or some native type. If I have to write an ostream operator to use the library it doesn't make it as a 'double replacement'. I agree with you on this point.
However I hope you do agree with me that everybody uses units a bit differently so it is impossible to provide all possibilities.
Not if you give the user the correct hooks in the library.
Even if you supported all existing standards many people will want non standard units. This means that most of the units will have to be user defined.
I agree on being able to generate new unit types. The 'physics only' view of the world isn't very interesting to me. I'm really much more interested in the general idea of 'value types' of which units part of the puzzle.
Now let us imagine we could realize every infterface we wanted. How would the interface look like? For simple situations it should be simple and be able to adabte to complex ones.
The simplest situation would be to have a non unicode unit postfix. So the ideal interface would look similar to
typedef unit<length, "m"> meter;
This isn't valid code...can't give char strings to templates.
by not providing I/O support we actually get extremly close to this
typedef unit<length> meter; ostream&operator<<(ostream&out, meter n){return out<<n.raw()<<"m";}
The problem is hardcoding the "m" anywhere -- this shouldn't be done. You need an I/O facet that has the defaults and can be overridden by the user at runtime. This allows different output for the same value in the same process. Your view of how to solve this is on the wrong course in my view... Just to give you the flavor of how this actually needs to look, here's some code to output a 'date duration' type: template <class CharT, class TraitsT> inline std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& os, const date_duration& dd) { boost::io::ios_flags_saver iflags(os); typedef boost::date_time::date_facet<date, CharT> custom_date_facet; std::ostreambuf_iterator<CharT> output_itr(os); if (std::has_facet<custom_date_facet>(os.getloc())) std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), dd); else { custom_date_facet* f = new custom_date_facet(); std::locale l = std::locale(os.getloc(), f); os.imbue(l); f->put(output_itr, os, os.fill(), dd); } return os; } As you can see it's reasonably complex to output what amounts to an integer across wide streams and with customizeable formats. But really, output is trivial compared to input.
It is indeed a bit verbose but every feasable unit interface is in my eyes more verbose. The only real alternative is a macro that expands to the operator<<.
You may need macros...it isn't easy I agree.
In more complex situations you run accross the problem that you can no longer deduce the correct unit type. This is also the reason why PQU (= Physical Quantities Units) has introduced annomymous units. However in what way does this help? None that I can think of because in both situation (meaning non printable units and annomymous units) the users has to indicate how to print the units.
Agree.
The conclusion that I come to is there is nothing that even an ideal interface could provide that isn't already just as simply possible with the interface the iostreams provide for every type.
All you can do is making things more complicated.
Well I believe that someone should attempt to create a toolkit that will allows these user defined units to be created with a minimum of pain and fuss. It may indeed require some macros and other 'ugly coding' in the library...but once it works the user doesn't care much about that -- only that they don't have to figure out how to write a flexible, wide string enabled, i/o framework b/c that's in the library. Don't take this as criticism -- I suppose I could have taken this on by now given my experience. I'm just hoping someone will take up my challenge ;-) Jeff

"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4796E.4030406@crystalclearsoftware.com...
I agree on being able to generate new unit types. The 'physics only' view of the world isn't very interesting to me.
That's quite funny, given that time is a physical quantity. regards Andy Little

Andy Little wrote:
"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4796E.4030406@crystalclearsoftware.com...
I agree on being able to generate new unit types. The 'physics only' view of the world isn't very interesting to me.
That's quite funny, given that time is a physical quantity.
Well for physicists it is -- but really it isn't. Leap seconds are decided by a committee...timezones are too. One thing I agree with though, if everyone would just start using a monotonic time system life would be so much easier ;-) Jeff

"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4859E.9090201@crystalclearsoftware.com...
Andy Little wrote:
"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4796E.4030406@crystalclearsoftware.com...
I agree on being able to generate new unit types. The 'physics only' view of the world isn't very interesting to me.
That's quite funny, given that time is a physical quantity.
Well for physicists it is -- but really it isn't. Leap seconds are decided by a committee...timezones are too. One thing I agree with though, if everyone would just start using a monotonic time system life would be so much easier ;-)
With all due respect, Boost date time doesnt treat time as a physical quantity, but it is primarily a physical quantity. Time will still exist long after the committee have all died, though I suppose they might think they could stop that scenario by voting against. I guess maybe Boost Date Time doesnt put time into its proper context, because if it did then there would be a *little* more work required, and not just on input output, but as you say that part isnt very interesting to you, but its probably pretty trivial to add I guess. regards Andy Little

Andy Little wrote:
"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4859E.9090201@crystalclearsoftware.com...
Andy Little wrote:
"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4796E.4030406@crystalclearsoftware.com...
I agree on being able to generate new unit types. The 'physics only' view of the world isn't very interesting to me. That's quite funny, given that time is a physical quantity. Well for physicists it is -- but really it isn't. Leap seconds are decided by a committee...timezones are too. One thing I agree with though, if everyone would just start using a monotonic time system life would be so much easier ;-)
With all due respect, Boost date time doesnt treat time as a physical quantity, but it is primarily a physical quantity. Time will still exist long after the
None of the users care...the point of the library isn't to treat it as a physical quantity.
committee have all died, though I suppose they might think they could stop that scenario by voting against. I guess maybe Boost Date Time doesnt put time into its proper context,
What is the "proper context" -- the rest of the units?
because if it did then there would be a *little* more work required, and not just on input output, but as you say that part isnt very interesting to you, but its probably pretty trivial to add I guess.
I'm sure you are insulting me, luckily I'm too dumb to get it. Regardless, this conversation is now off-topic and pointless. I've made my challenge -- you guys can choose to accept it or not. Jeff

"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F48C83.9060501@crystalclearsoftware.com...
Andy Little wrote:
"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4859E.9090201@crystalclearsoftware.com...
Andy Little wrote:
"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4796E.4030406@crystalclearsoftware.com...
I agree on being able to generate new unit types. The 'physics only' view of the world isn't very interesting to me. That's quite funny, given that time is a physical quantity. Well for physicists it is -- but really it isn't. Leap seconds are decided by a committee...timezones are too. One thing I agree with though, if everyone would just start using a monotonic time system life would be so much easier ;-)
With all due respect, Boost date time doesnt treat time as a physical quantity, but it is primarily a physical quantity. Time will still exist long after the
None of the users care...the point of the library isn't to treat it as a physical quantity.
Just trying to "raise the bar a little". The vison thing... you know ;-)
committee have all died, though I suppose they might think they could stop that scenario by voting against. I guess maybe Boost Date Time doesnt put time into its proper context,
What is the "proper context" -- the rest of the units?
A time entity needs to be compatible with a physical quantities library. otherwise its of little use to me FWIW.
because if it did then there would be a *little* more work required, and not just on input output, but as you say that part isnt very interesting to you, but its probably pretty trivial to add I guess.
I'm sure you are insulting me, luckily I'm too dumb to get it. Regardless, this conversation is now off-topic and pointless. I've made my challenge -- you guys can choose to accept it or not.
Not. regards Andy Little

Andy Little wrote:
"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4796E.4030406@crystalclearsoftware.com...
I agree on being able to generate new unit types. The 'physics only' view of the world isn't very interesting to me.
That's quite funny, given that time is a physical quantity.
So? Just because time is one of the quantities I'm going to use, I should use a full physical dimension library? In particular, many of us need to use calendar time units, which are not and should not be handled by any physical dimensions library. And conversions between the different units (days, weeks, months, years) need to be handled carefully and definitely not automatically. Ben appears to have implemented a core library that I believe has a much broader range of applications than a physical dimensions library. I have reason to believe that somewhere inside your library, you have the same thing implemented.

"Deane Yang" <deane_yang@yahoo.com> wrote in message news:ed22vq$4gc$1@sea.gmane.org...
Andy Little wrote:
"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4796E.4030406@crystalclearsoftware.com...
I agree on being able to generate new unit types. The 'physics only' view of the world isn't very interesting to me.
That's quite funny, given that time is a physical quantity.
So? Just because time is one of the quantities I'm going to use, I should use a full physical dimension library?
Kind of goes against the argument that money 'Units' is essential in a physical quantities library though don't it? <..>
Ben appears to have implemented a core library that I believe has a much broader range of applications than a physical dimensions library. I have reason to believe that somewhere inside your library, you have the same thing implemented.
That is not now or for the foreeable future a goal of Quan. regards Andy Little

Andy Little wrote:
Ben appears to have implemented a core library that I believe has a much broader range of applications than a physical dimensions library. I have reason to believe that somewhere inside your library, you have the same thing implemented.
That is not now or for the foreeable future a goal of Quan.
This sounds reasonable to me. It appears to me that there are two distinct libraries with two distinct sets of applications that we've all been discussing as if they were the same thing. I think Ben, Jeff, and I want the "no pre-defined dimensions" one, while yours is a physical dimensions library.

Deane Yang wrote:
Andy Little wrote:
Ben appears to have implemented a core library that I believe has a much broader range of applications than a physical dimensions library. I have reason to believe that somewhere inside your library, you have the same thing implemented. That is not now or for the foreeable future a goal of Quan.
This sounds reasonable to me. It appears to me that there are two distinct libraries with two distinct sets of applications that we've all been discussing as if they were the same thing. I think Ben, Jeff, and I want the "no pre-defined dimensions" one, while yours is a physical dimensions library.
I agree...seems like there's room for both. User defined units is a long and old debate. Some of us aren't going to give up on it :-) Jeff

"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4A0E8.9090405@crystalclearsoftware.com...
Deane Yang wrote:
Andy Little wrote:
Ben appears to have implemented a core library that I believe has a much broader range of applications than a physical dimensions library. I have reason to believe that somewhere inside your library, you have the same thing implemented. That is not now or for the foreeable future a goal of Quan.
This sounds reasonable to me. It appears to me that there are two distinct libraries with two distinct sets of applications that we've all been discussing as if they were the same thing. I think Ben, Jeff, and I want the "no pre-defined dimensions" one, while yours is a physical dimensions library.
I agree...seems like there's room for both. User defined units is a long and old debate. Some of us aren't going to give up on it :-)
I don't agree. As I understand it Ben Strassers Boost. Units library is going to provide all the functionality in Quan and more, in which case there is no room for both. AFAICS Bens library is going be more generic, encompassing all the current functionality in Quan,so it looks like there is no point in resubmitting Quan for another review, as it would soon be superceded by Boost.Units anyway. I look forward to seeing the Boost Units library proposal soon and I can then retire Quan and become just a happy Boost. Units user. regards Andy Little

"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4796E.4030406@crystalclearsoftware.com...
Just to give you the flavor of how this actually needs to look, here's some code to output a 'date duration' type:
template <class CharT, class TraitsT> inline std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& os, const date_duration& dd) { boost::io::ios_flags_saver iflags(os); typedef boost::date_time::date_facet<date, CharT> custom_date_facet; std::ostreambuf_iterator<CharT> output_itr(os); if (std::has_facet<custom_date_facet>(os.getloc())) std::use_facet<custom_date_facet>(os.getloc()).put(output_itr, os, os.fill(), dd); else { custom_date_facet* f = new custom_date_facet(); std::locale l = std::locale(os.getloc(), f); os.imbue(l); f->put(output_itr, os, os.fill(), dd);
} return os; }
As you can see it's reasonably complex to output what amounts to an integer across wide streams and with customizeable formats. But really, output is trivial compared to input.
I also think that this is kind of funny. On the one hand you provide the pretty complex code just to output a date, OTOH it seems that the Boost.Units ( not now physical units afaics, certainly not Quan anyway) library is now required to provide a generic output for any unit, including AFAICS, money, physical quantities, network data, not forgetting apples and oranges, per hour of course. and presumably with as much flexibility on each entity as the above. Good luck with that ! regards Andy Little

Andy Little wrote:
"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4796E.4030406@crystalclearsoftware.com...
Just to give you the flavor of how this actually needs to look, here's some code to output a 'date duration' type:
...snip details...
As you can see it's reasonably complex to output what amounts to an integer across wide streams and with customizeable formats. But really, output is trivial compared to input.
I also think that this is kind of funny. On the one hand you provide the pretty complex code just to output a date, OTOH it seems that the Boost.Units ( not now physical units afaics, certainly not Quan anyway) library is now required to
I didn't say it was required...just trying to raise the bar and get the library to do something truly revolutionary and useful :-)
provide a generic output for any unit, including AFAICS, money, physical quantities, network data, not forgetting apples and oranges, per hour of course. and presumably with as much flexibility on each entity as the above.
Good luck with that !
If it isn't hard, it isn't worth doing, right? I can write the 'braindead' one liner version of operator<<() -- why depend on a library for that? Maybe I'm wrong, but that's what I thought I read as being proposed. I believe it can be done and you could probably steal much of the code from date-time to do it. 99% of of the code doesn't really depend on what is being output/input. But first you have to have the vision that it's needed...I'm trying to help with the vision thing ;-) Jeff

"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F48A27.5060908@crystalclearsoftware.com...
Andy Little wrote:
"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4796E.4030406@crystalclearsoftware.com...
Just to give you the flavor of how this actually needs to look, here's some code to output a 'date duration' type:
...snip details...
As you can see it's reasonably complex to output what amounts to an integer across wide streams and with customizeable formats. But really, output is trivial compared to input.
I also think that this is kind of funny. On the one hand you provide the pretty complex code just to output a date, OTOH it seems that the Boost.Units ( not now physical units afaics, certainly not Quan anyway) library is now required to
I didn't say it was required...just trying to raise the bar and get the library to do something truly revolutionary and useful :-)
FWIW Quan already provides comprehensive support for dealing with physical quantities. AFAICS the recent spate of Units libraries is very much based on the PQS review, and PQS was the result of a great deal of original work in trying to identify and solve problems in the physical quantity domain. Note that all the current proposals basically lay out a quantity as Quan does, and this was innovated in PQS, a break from the previous approach , all then based on SI Units. Unfortunately nothing I have seen has anything like the functionality already available in Quan. I too could make claims that Quan 'is going to do X and Y at some unspecified time'. I don't do that. I prefer to show what I have already achieved, demonstrated, proven, tested and what is working and available now for use. I don't see much benefit in discussing 'visionary vapourware' without at least some use cases and preferable some code,tests and docs. As far as being useful, the feedback I have had suggest that those that have tried out the library have found it very useful.
provide a generic output for any unit, including AFAICS, money, physical quantities, network data, not forgetting apples and oranges, per hour of course. and presumably with as much flexibility on each entity as the above.
Good luck with that !
If it isn't hard, it isn't worth doing, right? I can write the 'braindead' one liner version of operator<<() -- why depend on a library for that? Maybe I'm wrong, but that's what I thought I read as being proposed. I believe it can be done and you could probably steal much of the code from date-time to do it. 99% of of the code doesn't really depend on what is being output/input. But first you have to have the vision that it's needed...I'm trying to help with the vision thing ;-)
Great., now... Show Me The Code! regards Andy Little

Jeff Garland <jeff <at> crystalclearsoftware.com> writes:
typedef unit<length, "m"> meter;
This isn't valid code...can't give char strings to templates. I was talking about an ideal world. ;)
The problem is hardcoding the "m" anywhere -- this shouldn't be done. You need an I/O facet that has the defaults and can be overridden by the user at runtime. This allows different output for the same value in the same process. Your view of how to solve this is on the wrong course in my view...
I depends on the situation. Some units are unique to the application. Here we probably wont need any internationalization so hard coding "m" will do the job just fine. There are however also other units. For example length units. It might be useful to let the programmer use meters in his program and have it output feet based on the local in the stream. What I mean is something like: cout.imbue(new unit_out_facet<length, feet>("", "ft")); wcout.imbue(new unit_wout_facet<length, feet>(L"", L"ft")); //or cout.imbue(new unit_out_facet<length, meter>("", "m")); wcout.imbue(new unit_wout_facet<length, meter>(L"", L"m")); //... cout<<meter(4); // will print meter or feet based on the current local This seems as a good idea to me and this is possbile to implement. Input would be a bit more tricky.
Don't take this as criticism -- I suppose I could have taken this on by now given my experience. I'm just hoping someone will take up my challenge
No, I don't. I like hearing other peoples opinions.

Ben Strasser wrote:
Jeff Garland <jeff <at> crystalclearsoftware.com> writes:
typedef unit<length, "m"> meter; This isn't valid code...can't give char strings to templates. I was talking about an ideal world. ;)
Ok, well we don't have that world...
The problem is hardcoding the "m" anywhere -- this shouldn't be done. You need an I/O facet that has the defaults and can be overridden by the user at runtime. This allows different output for the same value in the same process. Your view of how to solve this is on the wrong course in my view...
I depends on the situation. Some units are unique to the application. Here we probably wont need any internationalization so hard coding "m" will do the job just fine.
Boost is an international organization with an international audience so it's a different context to do something only for yourself.
There are however also other units. For example length units. It might be useful to let the programmer use meters in his program and have it output feet based on the local in the stream.
What I mean is something like:
cout.imbue(new unit_out_facet<length, feet>("", "ft")); wcout.imbue(new unit_wout_facet<length, feet>(L"", L"ft")); //or cout.imbue(new unit_out_facet<length, meter>("", "m")); wcout.imbue(new unit_wout_facet<length, meter>(L"", L"m")); //... cout<<meter(4); // will print meter or feet based on the current local
This seems as a good idea to me and this is possbile to implement.
On the right track, but this scares me a bit. I'm not sure I want conversions in the facet code. I think I'd rather the user do that explicitly.
Input would be a bit more tricky.
Input is much harder...because you only have access to an input iterator. You can't backtrack. So suppose you want to handle input like this: 10 m 10 meters 10 microseconds The first 2 are a valid length -- the last isn't. Anyway, it's sticky.
Don't take this as criticism -- I suppose I could have taken this on by now given my experience. I'm just hoping someone will take up my challenge No, I don't. I like hearing other peoples opinions.
Good :-) Jeff

"Jeff Garland" <jeff@crystalclearsoftware.com> wrote in message news:44F4A262.4070607@crystalclearsoftware.com...
Ben Strasser wrote:
Jeff Garland <jeff <at> crystalclearsoftware.com> writes:
typedef unit<length, "m"> meter; This isn't valid code...can't give char strings to templates. I was talking about an ideal world. ;)
Ok, well we don't have that world...
The problem is hardcoding the "m" anywhere -- this shouldn't be done. You need an I/O facet that has the defaults and can be overridden by the user at runtime. This allows different output for the same value in the same process. Your view of how to solve this is on the wrong course in my view...
I depends on the situation. Some units are unique to the application. Here we probably wont need any internationalization so hard coding "m" will do the job just fine.
Boost is an international organization with an international audience so it's a different context to do something only for yourself.
There are however also other units. For example length units. It might be useful to let the programmer use meters in his program and have it output feet based on the local in the stream.
What I mean is something like:
cout.imbue(new unit_out_facet<length, feet>("", "ft")); wcout.imbue(new unit_wout_facet<length, feet>(L"", L"ft")); //or cout.imbue(new unit_out_facet<length, meter>("", "m")); wcout.imbue(new unit_wout_facet<length, meter>(L"", L"m")); //... cout<<meter(4); // will print meter or feet based on the current local
This seems as a good idea to me and this is possbile to implement.
On the right track, but this scares me a bit. I'm not sure I want conversions in the facet code. I think I'd rather the user do that explicitly.
Input would be a bit more tricky.
Input is much harder...because you only have access to an input iterator. You can't backtrack. So suppose you want to handle input like this: 10 m 10 meters 10 microseconds
The first 2 are a valid length -- the last isn't. Anyway, it's sticky.
FWIW I think that the problems of I/O of quantities( at least in SI Units ) are orthogonal to the main bulk of a quantities library. IOW its probably not that difficult to work on this type of functionality independent ( as far as possible) of a particular library. regards Andy Little

Jeff Garland <jeff <at> crystalclearsoftware.com> writes:
On the right track, but this scares me a bit. I'm not sure I want conversions in the facet code. I think I'd rather the user do that explicitly.
Actually if a global implicit conversion has been explicity made avaiable by the user then the facet code will use it. What should happen if the user tries to print a unit for which no pre- and postfix facet is in the locale? Should it fail or just print the raw number type without them. For the moment (on my local disk) it's implemented as the later but I will likly change that.
Input is much harder...because you only have access to an input iterator. You can't backtrack. So suppose you want to handle input like this: 10 m 10 meters 10 microseconds
The first 2 are a valid length -- the last isn't. Anyway, it's sticky. Why isn't the last valid?
Anyway, do you have any tips on how to parse such things? All I can think of breaks in certain situations. Perhaps I should only provide textual represenations I/O and let user handle this with getline or somthing similar. Not very elegant.

I'm having a serious problem with facets and if I don't find a solution for it facets are definately out of the game. Several unit types can describe the same unit. For example unit<quantity<length, 1, mass, 1> > is the same as unit<quantity<mass, 1, length, 1> > but when it comes to types they are different. The unit code can cope with this. facets on the other hand requier an exact type to be able to use unit specific facets. I only see 3 possible solutions: 1) Add a facet for each permutation of the base quantities (= length & time_ here). This is only acceptable for small quantities because the number of combinations grows too fast. Also I don't like the idea of spamming the locale objects full. 2) Make the quantity lists sortable and only look up the sorted versions in the locale objects. The problem is that for this I need some smaller-as meta function to define the order. Unfortuately I have no idea on how to generate a default one (typeid unfortuately only return runtime objects). Letting the user generate one is not an option. For example user 1 defines struct mass:base_unit<mass>{}; struct length:base_unit<length>{}; template<> struct is_smaller<mass, length>:boost::true_type{}; Now user 2 defines but knows nothing about user 1 struct time_:base_unit<time_>{}; Now user 3 defines typedef quantity<length, 1, time, -1>velocitiy; Peng! We're dead. user3 has to define the order between the quantities of user 1 and those of user 2. Still possible but gets very verbose and limits the flexibility. 3) First order the base units using the exponents. If there are 2 units with the same exponents spam all permutations. This should work in nearly all real world examples but you can without any problems construct senarios in which even the filling of the locales would last ages. Does anybody have an idea on how to solve this? A way to sort arbitrary types would be ideal.

Ben Strasser said: (by the date of Fri, 1 Sep 2006 15:15:14 +0000 (UTC))
Does anybody have an idea on how to solve this? A way to sort arbitrary types would be ideal.
If I recall correctly Andrei Alexandrescu in his "modern C++ design" has written an example that sorts types in a list (a typelist) according to some compiler-decides criterion. I cannot look up it now, but if you can't find it, let me know, and I will look into the book. -- Janek Kozicki |

Janek Kozicki <janek_listy@wp.pl> writes:
Ben Strasser said: (by the date of Fri, 1 Sep 2006 15:15:14 +0000 (UTC))
Does anybody have an idea on how to solve this? A way to sort arbitrary types would be ideal.
If I recall correctly Andrei Alexandrescu in his "modern C++ design" has written an example that sorts types in a list (a typelist) according to some compiler-decides criterion.
He used inheritance relationships.
I cannot look up it now, but if you can't find it, let me know, and I will look into the book.
Why not just use mpl::sort? -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams <dave <at> boost-consulting.com> writes:
Why not just use mpl::sort?
Because AFAIK it needs some compairison metafunction as argument and I have none. But I solved my problem. It's actually quiet simple: typedef unit<quantity<length, 1, time_, -1> >meter1; typedef unit<quantity<time_, -1, length, 1> >meter2; // only overload for 1 unit ostream&operator<<(ostream&out, meter1); //... meter2 foo; cout<<foo; // implicit conversion does the ordering for me

Ben Strasser <strasser.ben@googlemail.com> writes:
David Abrahams <dave <at> boost-consulting.com> writes:
Why not just use mpl::sort?
Because AFAIK it needs some compairison metafunction as argument and I have none.
Well, if you can't formulate your "compiler-decided criterion" as a metafunction, neither Andrei's code nor mpl::sort will work for you. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"Ben Strasser" <strasser.ben@googlemail.com> wrote in message news:loom.20060829T180704-945@post.gmane.org...
In more complex situations you run accross the problem that you can no longer deduce the correct unit type. This is also the reason why PQU (= Physical Quantities Units) has introduced annomymous units. However in what way does this help? None that I can think of because in both situation (meaning non printable units and annomymous units) the users has to indicate how to print the units.
FWIW, if this is a statement regarding Quan, then it is incorrect regards Andy Little

Andy Little <andy <at> servocomm.freeserve.co.uk> writes:
"Ben Strasser" <strasser.ben <at> googlemail.com> wrote in message news:loom.20060829T180704-945 <at> post.gmane.org...
In more complex situations you run accross the problem that you can no longer deduce the correct unit type. This is also the reason why PQU (= Physical Quantities Units) has introduced annomymous units. However in what way does this help? None that I can think of because in both situation (meaning non printable units and annomymous units) the users has to indicate how to print the units.
FWIW, if this is a statement regarding Quan, then it is incorrect
Then please correct me. Somewhere in this same thread you said:
In the calculation:
force * distance;
The programmer might be dealing with a force acting at a moment, or the energy required to move an object. There is no way to tell from the calculation which. [...] , so the result is an anonymous quantity.
One could apply various rules [...], but as I can't apply a rule easily to the above case, I opted to apply the same rule to every case of dimensionful multiplication and division, which was to return an anonymous quantity and leave it to the programmer to decide which quantity they were dealing with.
The way I understood this is that the library isn't able to deduce what symbol corresponds to the units so the user has to make a choice. Did I misunderstand this or did I only get the terminology wrong?

"Ben Strasser" <strasser.ben@googlemail.com> wrote in message news:loom.20060829T195422-914@post.gmane.org...
Andy Little <andy <at> servocomm.freeserve.co.uk> writes:
"Ben Strasser" <strasser.ben <at> googlemail.com> wrote in message news:loom.20060829T180704-945 <at> post.gmane.org...
In more complex situations you run accross the problem that you can no longer deduce the correct unit type. This is also the reason why PQU (= Physical Quantities Units) has introduced annomymous units. However in what way does this help? None that I can think of because in both situation (meaning non printable units and annomymous units) the users has to indicate how to print the units.
FWIW, if this is a statement regarding Quan, then it is incorrect
Then please correct me. Somewhere in this same thread you said:
In the calculation:
force * distance;
The programmer might be dealing with a force acting at a moment, or the energy required to move an object. There is no way to tell from the calculation which. [...] , so the result is an anonymous quantity.
One could apply various rules [...], but as I can't apply a rule easily to the above case, I opted to apply the same rule to every case of dimensionful multiplication and division, which was to return an anonymous quantity and leave it to the programmer to decide which quantity they were dealing with.
The way I understood this is that the library isn't able to deduce what symbol corresponds to the units so the user has to make a choice.
Did I misunderstand this or did I only get the terminology wrong?
Quan provides a default output format for "anonymous quantities", but apparently these are unnecessary anyway so I really wouldnt about it, but please dont make incorrect statements regarding my library. Thankyou. regards Andy Little

Ben Strasser said: (by the date of Tue, 29 Aug 2006 16:23:30 +0000 (UTC))
The simplest situation would be to have a non unicode unit postfix. So the ideal interface would look similar to
typedef unit<length, "m"> meter;
maybe even something like this: typedef unit<length, "m" , 10, 0, 1 > meter; typedef unit<length, "in", 10,-2, 2.54 > inch; additional arguments are: power base, power exponent, conversion mutiplier, so we have: 10^0 * 1 = 1 meter 10^-2 * 2.54 = 1 inch With this *user defined* units we have two very nice advantages: 1. we do not force anybody to use any of the predefined unit systems, he can define any system he wants. Imperial people can have as well (total equivalent of above example): typedef unit<length, "m" , 10, 1, 3.937 > meter; typedef unit<length, "in", 10, 0, 1 > inch; 2. selecting power base makes it easy to work with units that operate with other bases, like 2^n, for example to measure storage capacity of a harddrive in MB. (lack of this ability was one of reasons to reject Quan's submission to boost (at that time under name 'pqs')). Also I fully agree that the only IO here is just operator<<, just like we have it provided for all fundamental types: int main() { typedef unit<length, "m" , 10, 0, 1 > meter; meter l(10); cout << "length: " << l << endl; // length: 10 m } And nothing more. operator<< uses string given as a unit name in the typedef, and that's all. No fancy creating of other strings that name the unit. At least, when you are going to have a variable that holds torque, you had first to make a typedef for that, right? And in that typedef there is a string with unit name already. That strips the library of hundreths (thousands?) of lines that try to support IO, try to create unit name strings from their dimensions, run into various problems what exponent to use in that name, etc, etc... Much simpler design, and much easier to use. need to use kilometers or feets? Then you also define it (Imperial example ;) typedef unit<length, "km", 10, 3, 3.937 > kilometer; typedef unit<length, "f" , 10, 1, 1.2 > feet; see? All the burden of exponent conversions are removed from the library (strips away hundreths of lines), and the user feels exactly whats going on. When someone need to convert from meters to feets he does just that: meter l(10); feet f; /*....*/ f=l; alternatively: feet f(l); Note: imperial notation is just an example here, it can be substituted for any unit system used in the world: astronomers operate in parsecs and AU (try storing parsecs in memory expressed in meters (an SI unit!)), physicists operate with time=space and speed of light=1 [unitless], etc.... -- Janek Kozicki |

Janek Kozicki <janek_listy <at> wp.pl> writes:
maybe even something like this:
typedef unit<length, "m" , 10, 0, 1 > meter; typedef unit<length, "in", 10,-2, 2.54 > inch;
additional arguments are: power base, power exponent, conversion mutiplier, so we have:
This is actually already implemented. See unit_converter.cpp for a usage example. The only only part that is missing is the automatique I/O.

"Andy Little" <andy@servocomm.freeserve.co.uk> wrote in message news:ecvi70$a01$1@sea.gmane.org...
}
quan::energy::J my_energy = my_mass * quan::pow<2>(my_distance / my_time);
Oops should be: quan::energy::J my_energy = 0.5 * my_mass * quan::pow<2>(my_distance / my_time); regards Andy Little

I uploaded a new version the compiles with VC 8.0 and g++ 3.4.2 . Please test if you can compile the examples provided with your compiler. You can find the file in the boost vault in the units directory in alternative_units.zip

Ben Strasser wrote:
I uploaded a new version the compiles with VC 8.0 and g++ 3.4.2 .
Please test if you can compile the examples provided with your compiler.
The new version does indeed compile with VC8. Thanks! Did I mention I'd like to be able to use my own number types (not built-in)? Would that be possible, too?

Deane Yang <deane_yang <at> yahoo.com> writes:
The new version does indeed compile with VC8. Thanks!
Did I mention I'd like to be able to use my own number types (not built-in)? Would that be possible, too?
Yes that is possible. There are 3 template parameters to the unit class. First te quantitiy, then the modifier and finally the raw number type. Infact it's not only limited to numbers. Everything that looks in some way like a number can be used. Vectors for example.
participants (8)
-
Andy Little
-
Ben Strasser
-
David Abrahams
-
Deane Yang
-
Eric Lemings
-
Janek Kozicki
-
Jeff Garland
-
Paul Giaccone