Component of the Week #14: bslim_formatguard

Summary:
  • Provides a guard for saving the formatting state of a stream object.

The task of managing the formatting state of output streams can be complex, especially when dealing with nested formatting requirements.

#include <bsl_iostream.h>

void decOutput(bsl::ostream &os, int value)
{
    // BUG: The author assumed that since `bsl::dec` is the default,
    // there's no need to set the output mode.
    os << "Decimal output of value: "
       << value
       << bsl::endl;
}

void hexOutput(bsl::ostream &os, int value)
{
    os << "Hexadecimal output of value: "
       << bsl::hex
       << value
       << bsl::endl;

    // BUG: Doesn't reset the stream state after using `bsl::hex`.
}

int main() {
    decOutput(bsl::cout, 15); // ok, outputs 15
    hexOutput(bsl::cout, 15); // ok, outputs f

    decOutput(bsl::cout, 15); // BUG: outputs f -- stream still in `hex`
                              //      mode
}

The BDE component bslim_formatguard simplifies this process by providing a guard that automatically saves and restores the formatting state of a stream.

The state that is saved is

  • The fmtflags state

  • The floating-point precision

  • The fill char

#include <bslim_formatguard.h>
#include <bsl_iostream.h>
#include <bsl_iomanip.h>

using namespace BloombergLP;

void decOutput(bsl::ostream &os, int value)
{
    bslim::FormatGuard osGuard(&os);

    // Now we can change the mode without worries - the `FormatGuard` will
    // reset it on scope exit.
    os << "Decimal output of value: "
       << bsl::dec
       << value
       << bsl::endl;
}

void hexOutput(bsl::ostream &os, int value)
{
    bslim::FormatGuard osGuard(&os);

    // Again, we can change the mode without worries - the `FormatGuard`
    // will reset it on scope exit.
    // `setw` resets on the next `<<` while `hex` and `setfill` do not
    // reset.  With `FormatGuard` we don't need to remember that
    // distinction.
    os << "Hexadecimal output of value: 0x"
       << bsl::hex
       << bsl::setfill('0')
       << bsl::setw(8)
       << value
       << bsl::endl;
}

int main() {
    decOutput(bsl::cout, 4093); // OK: outputs 4093
    hexOutput(bsl::cout, 4093); // OK: outputs 0x00000ff5

    // No bug!
    decOutput(bsl::cout, 4093); // OK: outputs 4093
}

There’s more to bslim::FormatGuard than the simple examples we’ve shown here — it can handle any number of formatting changes and integrates seamlessly with any implementation of bsl::basic_ostream.

Check out the documentation for bslim_formatguard for details.