Boost logo

Boost :

Subject: [boost] Boost.Units does not honor setw width?
From: Paul A. Bristow (pbristow_at_[hidden])
Date: 2012-08-17 12:07:11


> -----Original Message-----
> From: Paul A. Bristow [mailto:pbristow_at_[hidden]]
> Sent: Thursday, August 09, 2012 4:44 PM
> To: 'boost_at_[hidden]'
> Subject: RE: [boost] [type_erasure] Review started (July 18-27, 2012)

Flushed with success using Steven Watanabe's type_erase for printing columns,
I have enjoyed extending it to use a fixed column width.

But I have stumbled on a feature of Boost.Units output
where Boost.Units does not honor the iostream width fully.

This can be seen in this minimal example:

     std::cout << std::setw(20) << 'm' << std::endl;

  outputs 19 spaces and 'm', total 20 as expected.

     quantity<length> ql = 2345.6 * meters;
     std::cout << std::setw(20) << ql << std::endl;

outputs
            2345.6 m

but the m does not line up with the previous 'm'.

There are 14 leading spaces and 5 digits, 1 period and a space and letter m for the unit, a total of
22.

The reason is that the first item value() is output using the ios width setting, but the second
unit() 'm' (and separating space) is not,
as in this line in io.hpp .

  os << q.value() << ' ' << Unit()

I have 'cured' this 'bug' (I suspect it is a feature really) thus in boost/units/io.hpp

template<class Char, class Traits, class Unit, class T>
inline std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, const
quantity<Unit, T>& q)
{
    if (units::get_autoprefix(os) == autoprefix_none)
    {
        std::streamsize w = os.width();
        if (w > 0)
        { // Need to build a single string with the width specified
          // (or outputting severally would not honour the width).
          std::ostringstream oss;
          oss << q.value() << ' ' << Unit();
          os << oss.str();
        }
        else
        { // No os.width set (so save the time needed to construct an ostringstream?)
          os << q.value() << ' ' << Unit();
        }
    }

This works for no_prefix, giving the expected number of leading spaces.

But not for autoprefix - when a similar trick looks to get much more complicated
(and when I start to get that 'angels fear to tread' feeling ;-)

Of course the jaggedness of the layout becomes clearer both as the units get longer and get
auto-prefixes (eg engineering).

And there is a similar problem using a User defined Type like the measurement.hpp example in
std::ostream& operator<<

       os << val.value() << "(+/-" << val.uncertainty() << ")";

where the second item is additional to the width, not included in it.

1 But I am not sure if this is wise. Is this a 'feature'?

2 Is this the best way of solving it?

3 Can/how should this be applied to autoprefix?

4 Should submit a ticket for this?

Paul

---
Paul A. Bristow,
Prizet Farmhouse, Kendal LA8 8AB  UK
+44 1539 561830  07714330204
pbristow_at_[hidden]

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk