#include <mutex>
#include <iostream>


class locked_stream
{
	static std::mutex s_out_mutex;
 	
	std::unique_lock<std::mutex> lock_;
	std::ostream* stream_; // can't make this reference so we can move

public:
	locked_stream(std::ostream& stream)
		: lock_(s_out_mutex)
		, stream_(&stream)
    { }
  
	locked_stream(locked_stream&& other)
		: lock_(std::move(other.lock_))
		, stream_(other.stream_)
	{
		other.stream_ = nullptr;
	}
  
    friend locked_stream&& operator << (locked_stream&& s, std::ostream& (*arg)(std::ostream&))
    {
		(*s.stream_) << arg;
    	return std::move(s);
    }
  
  	template <typename Arg>
    friend locked_stream&& operator << (locked_stream&& s, Arg&& arg)
    {
		(*s.stream_) << std::forward<Arg>(arg);
    	return std::move(s);
    }
};

std::mutex locked_stream::s_out_mutex{};

locked_stream locked_cout()
{
	return locked_stream(std::cout);
}

int main (int argc, char * argv[])
{
 	locked_cout() << "hello world: " << 1 << 3.14 << std::endl;
	return 0;
}