2

This is an academic question.

sdt::mutex m;
typedef std::lock_guard<std::mutex> G;

void thread1(){
  G g(m);       
  std::cout << std::setw(9);
  std::cout << 3.14;
  std::cout << std::endl;
}

void thread2(){
  G g(m);       
  std::cout << std::setw(7);
  std::cout << 3.14;
  std::cout << std::endl;
}

My problem is that the formatting is bound to the output stream, so I need to set all the formatting options ever invented on my thread if I want to be sure about the output I produce. Which will or will not work next year.

  • Is there any way to reset formatting to default without setting everything by hand?
  • If not, what are the good workarounds?
    • For example should I create and keep an std::ostringstream locally on my thread and write oss.str() to std::cout?
Notinlist
  • 16,144
  • 10
  • 57
  • 99

1 Answers1

2

I've used boost for brevity but you could write your own optional and state saver.

#include <mutex>
#include <iostream>
#include <iomanip>
#include <tuple>
#include <utility>
#include <boost/io/ios_state.hpp>
#include <boost/optional.hpp>

std::mutex m;

struct save_and_lock
{
    boost::optional<boost::io::ios_all_saver> saver;
    std::unique_lock<std::mutex> lock;

    void init(std::ostream& os)
    {
        lock = std::unique_lock<std::mutex>(m);
        saver.emplace(os);
        os.flags(std::ios_base::fmtflags(0));
    }

    friend std::ostream& operator<<(std::ostream& os, save_and_lock&& s)
    {
        s.init(os);
        return os;
    }
};

void thread1(){
    std::cout << save_and_lock() << std::setw(9) << 3.14 << std::endl;
}

void thread2(){
    std::cout << save_and_lock() << std::setw(9) << 3.14 << std::endl;

}

This will work because the evaluation order of user-defined operator << is left to right.

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142