Search code examples
c++boostformattingboost-units

Using printf with boost::units::quantity values


The boost::units library provides a nice way to write quantity values to a stream, see for example.

Can I use printf with the quantity values instead of using the output stream? I have a fair amount of code which has formatted the output nicely using printf and I would like to keep the formatting. Passing the quantity into say

quantity<mass_density> rho = 1.0 * mass_density;
printf("rho %6.2e\n", rho);

throws the warning

warning: format ‘%e’ expects argument of type ‘double’, but argument 2 has type ‘boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension, boost::units::static_rational<-0x00000000000000003l> >, boost::units::list<boost::units::dim<boost::units::mass_base_dimension, boost::units::static_rational<1l> >, boost::units::dimensionless_type> >, boost::units::homogeneous_system<boost::units::list<boost::units::si::meter_base_unit, boost::units::list<boost::units::scaled_base_unit<boost::units::cgs::gram_base_unit, boost::units::scale<10l, boost::units::static_rational<3l> > >, boost::units::list<boost::units::si::second_base_unit, boost::units::list<boost::units::si::ampere_base_unit, boost::units::list<boost::units::si::kelvin_base_unit, boost::units::list<boost::units::si::mole_base_unit, boost::units::list<boost::units::si::candela_base_unit, boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<boost::units::angle::steradian_base_unit, boost::units::dimensionless_type> > > > > > > > > > > >’ [-Wformat]

I could just use rho.value() instead, but I would like to output the units if possible (even if I have update the format string).

I think the answer is in here, http://www.boost.org/doc/libs/1_52_0/doc/html/boost_units/Reference.html#header.boost.units.io_hpp


Solution

  • The list of format specifiers is fixed by the language. "%e" outputs a double, "%d" outputs an int etc. There's nothing that would output an object of type quantity<mass_density>, or any other object of a class type.

    You can have this:

    template <typename Unit, typename T>
    string symbolic_units(const quantity<Unit, T> &)
    {
        return symbol_string(Unit());
    }
    
    int main()
    {
        quantity<mass_density> x;
        x = 3.72 * kilogram_per_cubic_meter;
    
        printf ("%g %s\n", x.value(), symbolic_units(x).c_str());
    }
    

    but not much more. Unless you are willing to use streams of course.