
I am trying to create a set of units to use in a library, but I having trouble getting IO to work for some of them. Here is a simple example that demonstrates the problem. ============================ #include<iostream> #include <boost/units/systems/si.hpp> #include <boost/units/systems/si/io.hpp> using namespace boost::units; // short hand for meter namespace t { typedef si::length m; } namespace i { BOOST_UNITS_STATIC_CONSTANT( m, t::m ); } // centimeter namespace t { typedef make_scaled_unit< si::length, scale< 10, static_rational<-2> > >::type cm; } namespace i { BOOST_UNITS_STATIC_CONSTANT( cm, t::cm ); } // meter squared namespace t { typedef multiply_typeof_helper< m, m>::type m_m; } namespace i { BOOST_UNITS_STATIC_CONSTANT( m_m, t::m_m ); } // centimeter squared namespace t { typedef multiply_typeof_helper< cm, cm>::type cm_cm; } namespace i { BOOST_UNITS_STATIC_CONSTANT( cm_cm, t::cm_cm ); } // meter centimeter namespace t { typedef multiply_typeof_helper< m, cm>::type m_cm; } namespace i { BOOST_UNITS_STATIC_CONSTANT( m_cm, t::m_cm ); } // override default output, which prints "c(m^2)" namespace boost { namespace units { inline std::string name_string(const t::m_cm&) { return "meter centimeter"; } inline std::string symbol_string(const t::m_cm&) { return "m cm"; } } } // trying to overload output for centimeter squared namespace boost { namespace units { inline std::string name_string(const t::cm_cm&) { return "centimeter squared"; } inline std::string symbol_string(const t::cm_cm&) { return "cm^2"; } } } int main(int argc, char *argv[]) { std::cout << i::m << std::endl; std::cout << i::cm << std::endl; std::cout << i::m_m << std::endl; std::cout << i::m_cm << std::endl; //std::cout << i::cm_cm << std::endl; // this won't compile quantity<t::m_m> a1(100*i::cm_cm); std::cout << a1<< std::endl; // should be 0.01 m^2 quantity<t::m_m> a2(100*i::m_cm); std::cout << a2<< std::endl; // should be 1 m^2 return 0; } ============================ Basically, I am just trying to create a convenient set of short hands. Unit types are put in a 't' namespace and instances are put in a 'i' namespace with the same name. This works fine for doing calculations and conversions with the units, but I am having trouble with getting output to work for some of them. In the example above I create a centimeter unit by scaling the meter. Then I create three different area units with the product_typeof_helper struct: meter squared, meter centimeter, and centimeter squared. Conversions work for all three of these, but output will not work for the centimeter squared unit. The program above outputs m cm m^2 m cm 0.01 m^2 1 m^2 If I uncomment the line that tries to print i::cm_cm it won't compile. I get an error that says 'symbol' is not a member of ... and points at a line that says str += Begin::item::symbol() I can't understand why it doesn't work for a product of two scaled units. cdclark

AMDG On 10/04/2017 07:58 PM, CD Clark via Boost-users wrote:
<snip> // centimeter namespace t { typedef make_scaled_unit< si::length, scale< 10, static_rational<-2> > >::type cm; } namespace i { BOOST_UNITS_STATIC_CONSTANT( cm, t::cm ); }
<snip>
// centimeter squared namespace t { typedef multiply_typeof_helper< cm, cm>::type cm_cm; } namespace i { BOOST_UNITS_STATIC_CONSTANT( cm_cm, t::cm_cm ); }
<snip> //std::cout << i::cm_cm << std::endl; // this won't compile
<snip> If I uncomment the line that tries to print i::cm_cm it won't compile. I get an error that says
'symbol' is not a member of ...
and points at a line that says
str += Begin::item::symbol()
I can't understand why it doesn't work for a product of two scaled units.
The reason that it fails is that the output code instantiates the default implementation even if you override it. The problem is that there is no symbol defined for 10^-4. In Christ, Steven Watanabe

The reason that it fails is that the output code instantiates the default implementation even if you override it. The problem is that there is no symbol defined for 10^-4.
Ah, that explains why it works for millimeter. Multiplying two millimeter units together gives 10^-6, which has a symbol. Does this mean that the IO can't handle units that have base units raised to some power that does not correspond to a symbol, or is this just supposed to be done a different way? Looking at the libraries definition of farad (which contains seconds to the fourth power), a derived dimension is defined for capacitance, and then an a unit for that dimension is created. Should I be creating the centimeter squared unit from the area dimension directly instead of trying to build it from already defined units? Thanks you for the help. cdclark

AMDG On 10/05/2017 12:44 PM, CD Clark via Boost-users wrote:
The reason that it fails is that the output code instantiates the default implementation even if you override it. The problem is that there is no symbol defined for 10^-4.
Ah, that explains why it works for millimeter. Multiplying two millimeter units together gives 10^-6, which has a symbol. Does this mean that the IO can't handle units that have base units raised to some power that does not correspond to a symbol, or is this just supposed to be done a different way?
Looking at the libraries definition of farad (which contains seconds to the fourth power), a derived dimension is defined for capacitance, and then an a unit for that dimension is created. Should I be creating the centimeter squared unit from the area dimension directly instead of trying to build it from already defined units?
Based on the way you're using this, I would recommend, setting up the scaling at the base unit level, instead of scaling the whole unit: namespace t { using cm = scaled_base_unit< si::meter_base_unit, scale<10, static_rational<-2> > >::unit_type; } This should make the output work the way you want automatically, as it causes cm*cm to be represented as (cm)^2 instead of (c^2)(m^2). In Christ, Steven Watanabe
participants (2)
-
CD Clark
-
Steven Watanabe