0

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

ccook
  • 5,869
  • 6
  • 56
  • 81
  • 1
    If you're going to use some C++ features, like Boost units, you may want to use the others, like streams. Most Boost classes have overloads for the stream operators, IIRC. If you need printf syntax, Boost provides a stream-based library that takes format strings. – ssube Dec 19 '12 at 18:57
  • @peachykeen Is that to say I should work with streams to be consistent with boost? – ccook Dec 19 '12 at 19:00
  • I would recommend using streams or Boost's C++ printf library, yes. It's more idiomatic and will help you avoid headaches like this, although it's not a global solution (varargs are more difficult with C++-style printing). – ssube Dec 19 '12 at 19:20
  • @peachykeen Unfortunately that's what I'm trying to keep, a custom printf with varargs. I can lose it, though, not the end of the world – ccook Dec 19 '12 at 19:24

1 Answers1

4

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.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243