How can I make an ostream reference an ofstream? (C++) - c++

I'm trying to make a simple logger class, and I want the ability to either log to either a generic ostream (cout/cerr) or a file. The design I have in mind is to allow the constructor to either take an ostream& or a filename, and in the latter case create an ofstream& and assign that to the class' private ostream& like so:
class Log {
private:
std::ostream& os;
public:
Log(std::ostream& os = std::cout): os(os) { }
Log(std::string filename) {
std::ofstream ofs(filename);
if (!ofs.is_open())
// do errorry things
os = ofs;
}
};
Doing such gives me an error that ofstream's assignment operator is private. Looking over that again, it occurred to me that making a reference to a local object probably wouldn't work, and making os a pointer to an ostream and declaring and deleting it on the heap worked with the ofstream case, though not with the ostream case, where the ostream already exists and is just being referenced by os (because the only place to delete os would be in the constructor, and I don't know of a way to determine whether or not os is pointing to an ofstream created on the heap or not).
So how can I make this work, i.e. make os reference an ofstream initialized with a filename in the constructor?

For one thing, you can't rebind references once they're created, you can only initialise them. You might think you could do this:
Log(std::string filename) : os(std::ofstream(filename)) {
if (!os.is_open())
// do errorry things
}
But that's no good because you are making os refer to a temporary variable.
When you need a reference that has to be optional, that is, it needs to refer to something sometimes and not other times, what you really need is a pointer:
class Log {
private:
std::ostream* os;
bool dynamic;
public:
Log(std::ostream& os = std::cout): os(&os), dynamic(false) { }
Log(std::string filename) : dynamic(true) {
std::ofstream* ofs = new std::ofstream(filename);
if (!ofs->is_open())
// do errorry things and deallocate ofs if necessary
os = ofs;
}
~Log() { if (dynamic) delete os; }
};
The above example is just to show you what is going on, but you probably will want to manage it with a smart pointer. As Ben Voigt points out, there are a lot of gotchas that will cause unforeseen and undesired behaviour in your program; for example, when you try to make a copy of the above class, it will hit the fan. Here is an example of the above using smart pointers:
class Log {
private:
std::unique_ptr<std::ostream, std::function<void(std::ostream*)>> os;
public:
Log(std::ostream& os = std::cout): os(&os, [](ostream*){}) { }
Log(std::string filename) : os(new std::ofstream(filename), std::default_delete<std::ostream>()) {
if (!dynamic_cast<std::ofstream&>(*os).is_open())
// do errorry things and don't have to deallocate os
}
};
The unusual os(&os, [](ostream*){}) makes the pointer point to the given ostream& but do nothing when it goes out of scope; it gives it a deleter function that does nothing. You can do this without lambdas too, it's just easier for this example.

The simplest thing to do is just bind your reference to an ofstream, and make sure the ofstream lives as long as your object:
class Log
{
std::ofstream byname;
std::ostream& os;
public:
Log(std::ostream& stream = std::cout) : byname(), os(stream) { }
Log(std::string filename) : byname(filename), os(this->byname)
{
if (!os)
// handle errors
}
};
Exception safe, can't leak, and the compiler-generated special member functions are sane.

In my Log/Debug class I find it useful to create a static member variable:
class debug {
public:
...
// Overload operator() for printing values.
template<class Type1>
inline debug&
operator()(const std::string& name1,
const Type1& value1)
{
// Prettify the name/value someway in another inline function.
_stream << print_value(name1, value1) << std::endl;
return *this;
}
private:
...
static std::ostream& _stream;
};
And then in my debug.cc file:
std::ostream& debug::_stream = std::cerr;

You have to initialize the os in the initialize list in the constructors, just as what you did in Log(std::ostream& os = std::cout): os_(os) { }, because os is a reference, which can not be assigned after initialized.

Related

Implicit argument to conversion constructors

tl;dr: Is there a way to add a default argument from the current scope to all implicit constructors in C++?
I am currently designing an interface for an embedded language in C++. The goal is to make the creation of syntactically correct expressions both typesafe and convenient. Right now, I think that learning a heavyweight implementation like boost::proto will itnroduce a too large latency into the development, so I attempt to roll my own implementation.
Here is a small demo:
#include <iostream>
#include <string>
#include <sstream>
class ExprBuilder
{
public:
ExprBuilder(const int val) : val(std::to_string(val)) {}
ExprBuilder(const std::string val) : val(val) {}
ExprBuilder(const char* val) : val(val) {}
ExprBuilder(const ExprBuilder& lhs, const ExprBuilder& arg) {
std::stringstream ss;
ss << "(" << lhs.val << " " << arg.val << ")";
val = ss.str();
}
const ExprBuilder operator()(const ExprBuilder& l) const {
return ExprBuilder(*this, l);
}
template<typename... Args>
const ExprBuilder operator()(const ExprBuilder& arg, Args... args) const
{
return (*this)(arg)(args...) ;
}
std::string val;
};
std::ostream& operator<<(std::ostream& os, const ExprBuilder& e)
{
os << e.val;
return os;
}
int main() {
ExprBuilder f("f");
std::cout << f(23, "foo", "baz") << std::endl;
}
As you can see, it is fairly simple to embedd expressions due to C++ overloading and implicit conversions.
I am facing a practical problem however: In the example above, all data was allocated in the form of std::string objects. In practice, I need something more complex (AST nodes) that are allocated on the heap and managed by a dedicated owner (legacy code, cannot be changed). So I have to pass a unique argument (said owner) and use it for the allocations. I'd rather not use a static field here.
What I am searching is a way to use ask the user to provide such an owner everytime the builder is used, but in a convenient way. Something like a dynamically scoped variable would be great. Is there a way to obtain the following in C++:
class ExprBuilder
{
...
ExprBuilder(const ExprBuilder& lhs, const ExprBuilder& arg) {
return ExprBuilder(owner.allocate(lhs, rhs)); // use the owner implicitly
}
...
};
int main() {
Owner owner; // used in all ExprBuilder instances in the current scope
ExprBuilder f("f");
std::cout << f(23, "foo", "baz") << std::endl;
}
Is this possible?
edit: I'd like to clarify why I do (up until now) not consider a global variable. The owner has to be manually released by the user of the builder at some point, hence I cannot create one ad hoc. Hence, the user might "forget" the owner altogether. To avoid this, I am searching a way to enforce the presence of the owner by the typechecker.
This is hardly possible without global / static variables, because without global / static information, the local variables Owner owner and ExprBuilder f cannot know anything about each other.
I think the cleanest way is to add a
static Owner* current_owner;
to the ExprBuilder class. Then you can add a new class ScopedCurrentOwnerLock, which sets the current_owner in the constructor and sets it to nullptr in the destructor. Then you can use it similar to a mutex lock:
class ScopedCurrentOwnerLock {
public:
ScopedCurrentOwnerLock(Owner const& owner) {
ExprBuilder::current_owner = &owner;
}
~ScopedCurrentOwnerLock() {
ExprBuilder::current_owner = nullptr;
}
};
int main() {
Owner owner;
ScopedCurrentOwnerLock lock(owner);
ExprBuilder f("f");
}
If you have access to the Owner code, you can omit the ScopedCurrentOwnerLock class and directly set / unset the pointer in the constructor/destructor of Owner.
Please be aware of the following two problems with this solution:
If the owner goes out of scope before the lock goes out of scope, you have an invalid pointer.
The static pointer has unpredictable behaviour if you have multiple locks at the same time, e. g. due to multithreading.
All your ExprBuilders have a dependancy on Owner, and you rightly don't want global state. So you have to pass owner to every constructor.
If you really don't want to add owner, to all your instantiations in a block, you can create a factory to pass it for you.
struct ExprBuilderFactory
{
Owner & owner;
ExprBuilder operator()(int val) { return ExprBuilder(owner, val); }
ExprBuilder operator()(char * val) { return ExprBuilder(owner, val); }
// etc
}
int main() {
Owner owner;
ExprBuilderFactory factory{ owner };
ExprBuilder f = factory("f");
}

How can an std::ostream be moved?

Since it is by design that std::ostream can't be moved the question becomes: how can an std::ostream be moved such that it can write to different destinations?
The basic objective is to have a factory function taking a URI and returning something, let's call it, omstream (output movable stream) which can be used like an std::ostream:
omstream stream_factory(std::string const& uri);
void process(std::ostream& out);
int main(int ac, char* av[]) {
omstream destination{ stream_factory(ac == 2? av[1]: "example.txt") };
process(destination);
}
The omstream would be responsible for properly moving the object:
class omstream
: public std::ostream {
// suitable members
public:
omstream(/* suitable constructor arguments */);
omstream(omstream&& other) // follow recipe of 27.9.1.11 [ofstream.cons] paragraph 4
: std:ios(std::move(other))
, std::ostream(std::move(other))
// move any members {
this->set_rdbuf(/* get the stream buffer */);
}
// other helpful or necessary members
};
The question is really what it takes to implement omstream (or, even a corresponding class template basic_omstream)?
You've almost got it right. Your example is move constructing the ios base twice. You should move only the direct base class. And assuming there is member streambuf, move that too:
class omstream
: public std::ostream {
// suitable members
public:
omstream(/* suitable constructor arguments */);
omstream(omstream&& other) // follow recipe of 27.9.1.11 [ofstream.cons] paragraph 4
: std: ostream(std::move(other)),
// move any members {
this->set_rdbuf(/* install the stream buffer */);
}
// other helpful or necessary members
};
I changed "get" to "install" in the set_rdbuf comment. Typically this installs a pointer to the member streambuf into the ios base class.
The current unorthodox design of the move and swap members of istream/ostream was set up to make the move and swap members of the derived classes (such as ofstream and omstream) more intuitive. The recipe is:
Move the base and members, and in the move constructor set the rdbuf.
It is that embedded rdbuf that is the complicating factor for the entire hierarchy.
The code posted in Howard's answer is a draft (based on the draft posted in the question). Howard's answer helped resolving a confusing issue with the virtual base class std::ios: the base class needs to be default constructed when moving a derived stream as the std::ios portion of a stream will explicitly be moved by the std::ostream move constructor using std::ios::move(). This answer merely fills in the missing bits.
The implementation below maintains a pointer to a stream buffer which normally expected to live on the heap and will be released upon destruction with the help of std::unique_ptr<...>. As it may be desirable to return an std::omstream the stream buffer of a long-lived stream, e.g., std::cout, the std::unique_ptr<...> is set up to use a deleter which may do nothing if the omstream doesn't own the stream buffer.
#include <ostream>
#include <memory>
#include <utility>
template <typename cT, typename Traits = std::char_traits<cT>>
class basic_omstream
: public std::basic_ostream<cT, Traits>
{
using deleter = void (*)(std::basic_streambuf<cT, Traits>*);
static void delete_sbuf(std::basic_streambuf<cT, Traits>* sbuf) {
delete sbuf;
}
static void ignore_sbuf(std::basic_streambuf<cT, Traits>*) {
}
std::unique_ptr<std::basic_streambuf<cT, Traits>, deleter> m_sbuf;
public:
basic_omstream()
: std::basic_ios<cT, Traits>()
, std::basic_ostream<cT, Traits>(nullptr)
, m_sbuf(nullptr, &ignore_sbuf) {
}
basic_omstream(std::basic_streambuf<cT, Traits>* sbuf,
bool owns_streambuf)
: std::basic_ios<cT, Traits>()
, std::basic_ostream<cT, Traits>(sbuf)
, m_sbuf(sbuf, owns_streambuf? &delete_sbuf: &ignore_sbuf) {
this->set_rdbuf(this->m_sbuf.get());
}
basic_omstream(basic_omstream&& other)
: std::basic_ios<cT, Traits>() // default construct ios!
, std::basic_ostream<cT, Traits>(std::move(other))
, m_sbuf(std::move(other.m_sbuf)) {
this->set_rdbuf(this->m_sbuf.get());
}
basic_omstream& operator=(basic_omstream&& other) {
this->std::basic_ostream<cT, Traits>::swap(other);
this->m_sbuf.swap(other.m_sbuf);
this->set_rdbuf(this->m_sbuf.get());
return *this;
}
};
typedef basic_omstream<char> omstream;
typedef basic_omstream<wchar_t> womstream;
Using an std::ofstream or an std::ostringstream to initialize an omstream doesn't work unless the corresponding stream outlives the omstream. In general a corresponding stream buffer will be allocated. The class omstream could, e.g., be used like in the code below which create a stream based on an URI given to a suitable factory function:
#include <iostream>
#include <sstream>
#include <fstream>
omstream make_stream(std::string const& uri) {
if (uri == "stream://stdout") {
return omstream(std::cout.rdbuf(), false);
}
else if (uri == "stream://stdlog") {
return omstream(std::clog.rdbuf(), false);
}
else if (uri == "stream://stderr") {
return omstream(std::cerr.rdbuf(), false);
}
else if (uri.substr(0, 8) == "file:///") {
std::unique_ptr<std::filebuf> fbuf(new std::filebuf);
fbuf->open(uri.substr(8), std::ios_base::out);
return omstream(fbuf.release(), true);
}
else if (uri.substr(0, 9) == "string://") {
return omstream(new std::stringbuf(uri.substr(9)), true);
}
throw std::runtime_error("unknown URI: '" + uri + "'");
}
int main(int ac, char* av[])
{
omstream out{ make_stream(ac == 2? av[1]: "stream://stdout") };
out << "hello, world\n";
}
If there are other stream buffers available which could be constructed from a URI, these could be added to the make_stream() function.

Common parent type ifstream and ofstream

I have a class that contains an std::ofstream and an std::ifstream (only one can be activated at a time). I would like to overload the operator() to return the current active stream. But what is the common base type of std::ofstream and std::ifstream to return a common reference ?
I would like to overload the operator() to return the current active stream This makes absolutely no sense and smells like a design flaw. Why do you want to return that? What should the caller of that operator be able to do with return value? It can neither do input nor output.
I dunno what you really want to do, but perhaps something like this could work for you, though it's dangerous
template<typename T> class wrapper
{
T*const ptr;
wrapper(T*p) : ptr(p) {}
public:
bool empty() const { return ptr; }
operator T& () const
{
if(empty()) throw some_exception("trying to use empty wrapper");
return *ptr;
}
friend some_class;
};
class some_class
{
ifstream _ifstream;
ofstream _ofstream;
bool ifstream_is_active;
bool ofstream_is_active;
public:
operator wrapper<ifstream> () const
{ wrapper<ifstream>(ifstream_is_active? &_ifstream : 0); }
operator wrapper<ofstream> () const
{ wrapper<ofstream>(ofstream_is_active? &_ofstream : 0); }
};
but this is dangerous, as you are potentially dealing with dangling pointers. You can avoid that by using shared_ptr (work this out yourself), but that means that some_class has no longer control over the lifetime of these streams.
Input and output streams are very different types. The only common base class they share is std::ios. And that doesn't have much in it besides some error checking stuff.
The two stream types only share the most basic of interfaces. They have little to do with one another, for obvious reasons.

C++ iostream Corruption using stringstream

I'm trying to write a really simple thread-safe logger. Ideally, I wanted it to work just like std::cout, wherein you could just overload the << operator and have everything magically show up in the log. I'm on a Windows machine, so here's the approach I tried:
// Threadsafe logger
class Logger
{
public:
Logger()
{
InitializeCriticalSection(&s);
}
~Logger()
{
DeleteCriticalSection(&s);
}
void Log(std::ostream const& os)
{
EnterCriticalSection(&s);
//std::cout << static_cast<std::stringstream const&>(os).str();
std::cout << os.rdbuf();
LeaveCriticalSection(&s);
}
private:
CRITICAL_SECTION s;
};
Notice that I've tried two approaches to the Log() function. The reason I accept an ostream is because that's what a stringstream seems to produce after the << operator is called. Both variants of the Log() function fail in the same way when I run this code:
#include <iostream>
#include <sstream>
#include <Windows.h>
int main(int argc, char* argv[])
{
Logger logger;
//logger.Log(std::stringstream("Test"));
logger.Log(std::stringstream("Another ") << "test");
std::cin.get();
}
Outputting the first line ("Test") works correctly and displays properly using both variants of the Log function. The second line outputs a mangled output:
testher
which is obviously test written over Another. What am I missing about the way these streams work? I tried making a flush call hoping that would fix things, but it did nothing.
How can I get this attempt at a thread-safe logger working correctly with the streams?
Using variadic templates:
void Log_impl(std::ostream &os) {} // recursion base case
template<typename T,typename... Us>
void Log_impl(std::ostream &os,T &&t,Us &&... us) {
os << std::forward<T>(t);
Log_impl(os,std::forward<Us>(us)...);
}
template<typename... Ts> void Log(Ts &&... ts) {
std::stringstream ss;
Log_impl(ss,std::forward<Ts>(ts)...);
fprintf(stdout,"%s\n",ss.str().c_str()); // thread safe output
}
usage:
Log("Another"," test ",100);
I haven't actually tested this code...
At least in my opinion, this approach to the problem is at least somewhat clumsy to use, since it requires you to create an auxiliary ostream object of some sort, stream data into it, and then pass that to your log. That doesn't seem to fit very closely with what you've said you'd really prefer.
I'm also a bit less than excited about how you've done your thread-locking code. Just for example, if you get an exception during your std::cout << os.rdbuf();, you can exit the scope without leaving the critical section.
I think I'd start with a thin wrapper around a critical section, add an RAII-style class to lock the critical section (and automatically unlock it when it goes out of scope), then use those in implementing the Log class. Further, I'd cheat and have the Log class use a template member function to accept almost any type of output in one fell swoop:
Edit: After some more thought, I've decided to embrace the notion that every problem can be solved with another level of indirection. To do that, I've added an intermediate transaction that encapsulates chaining the output of a number of items into a stringstream, then writing out that result as a thread-safe transaction.
#include <windows.h>
#include <iostream>
#include <sstream>
class crit_sect {
CRITICAL_SECTION cs;
void lock() { EnterCriticalSection(&cs); }
void unlock() { LeaveCriticalSection(&cs); }
friend class lock;
crit_sect(crit_sect const &); /* = delete; */
crit_sect &operator=(crit_sect const &other); /* = delete; */
public:
crit_sect() { InitializeCriticalSection(&cs); }
~crit_sect() { DeleteCriticalSection(&cs); }
};
class lock {
crit_sect &cs;
public:
lock(crit_sect &c) : cs(c) { cs.lock(); }
~lock() { cs.unlock(); }
};
class transaction {
std::ostringstream buffer;
public:
transaction(std::string const &s="") : buffer(s, std::ios::out | std::ios::ate) {}
template <class T>
transaction &operator<<(T const &t) {
buffer << t;
return *this;
}
friend std::ostream &operator<<(std::ostream &os, transaction const &t) {
return os << t.buffer.str();
}
};
class Log {
std::ostream &out;
crit_sect mutex;
public:
Log(std::ostream &sink) : out(sink) { }
template <class T>
void operator<<(T const &t) {
lock l(mutex);
out << t;
}
};
int main() {
Log l(std::cout);
l << "This is a string\n";
l << (transaction("Another ") << "Test");
return 0;
}
Since the log type doesn't support chaining, any attempt at chaining the output without using a transaction will fail (won't compile). Compared to the original, usage is still a bit cleaner though -- the extra parameters needed for the ostringstream ctor are hidden, and the name transaction clarifies what is being done, or rather, accomplished.
The problem isn't with the logger, rather it's with your use of stringstream.
When std::stringstream is initialized, the stream's position indicator is positioned at the beginning of the stream.
Now when you start writing to the string using '<<', you start writing at the position indicator, replacing whatever was there before.
To work around this, you can initialize the stringstream with
std::stringstream("Another ", stringstream::in | stringstream::out | std::stringstream::ate)
(as per http://www.cplusplus.com/reference/iostream/stringstream/stringstream/ )
<< doesn't send the null byte at the end of "test" into the temporary stringstream("Another ") you created, which is why you see "testher".

Need to make context available to C++ ostream insertion operators

For an API that I am working on, I want to allow the user to insert custom objects into an ostream, but these objects have no meaning on their own, and are too memory constrained to include an additional pointer or reference for context. (Think tens of millions of 16-/32-/48-bit objects in an embedded system with limited memory.)
Suppose the user initializes the underlying context, and looks up one of these objects:
DDB ddb("xc5vlx330t");
Tilewire tw = ddb.lookUpTilewire("DSP_X34Y0", "DSP_IMUX_B5_3");
...
std::cout << complexDataStructure;
In an entirely different scope, possibly nested far away from the user's explicit code, we may need to insert the object into an ostream, with ddb unavailable.
os << tw;
The actual value encapsulated by tw is 97,594,974, but the desired output is this:
DSP_IMUX_B5_3#[263,84] DSP "DSP_X34Y0" (1488#77406)
In order for this to work, the appropriate insertion operator would need access to ddb, but it cannot rely on static or global variables or functions (for multithreading reasons). What I'd like to do is allow the user to request and use a stream wrapper kind of like this:
ostream& wrappedCout = ddb.getWrappedOstream(std::cout);
The returned subclass of ostream would include a reference to ddb for use by special stream inserters that needed it, and a reference to the original stream—std::cout in this case—where it would forward all of its output.
Unfortunately, the inheritance or composition schemes that I have come up with are messy to code up (not an enormous concern), and possibly problematic for the user (a much larger concern). Any suggestions on how to elegantly make ddb available to insertion operators? I am marginally aware of boost.Iostreams, but not sure that it will help me out here.
Write a custom stream manipulator that stores a reference to ddb using the iword/pword mechanism. Here is an example, you'd need to add locking around the iwork_indexes map in a multithreaded program.
class dbb
{
public:
explicit dbb(int value) : m_value(value) {}
int value() const { return m_value; }
private:
int m_value;
};
class dbb_reliant_type
{
public:
dbb_reliant_type(const std::string& value) : m_value(value) {}
const std::string& value() const { return m_value; }
private:
std::string m_value;
};
typedef std::map<std::ostream*, int> iword_map;
iword_map iword_indexes;
inline int get_iword_index(std::ostream& os)
{
iword_map::const_iterator index = iword_indexes.find(&os);
if(index == iword_indexes.end())
{
std::pair<iword_map::iterator, bool> inserted = iword_indexes.insert(std::make_pair(&os, os.xalloc()));
index = inserted.first;
}
return index->second;
}
inline std::ostream& operator<<(std::ostream& os, const dbb& value)
{
const int index = get_iword_index(os);
if(os.pword(index) == 0)
os.pword(index) = &const_cast<dbb&>(value);
return os;
}
std::ostream& operator<<(std::ostream& os, const dbb_reliant_type& value)
{
const int index = get_iword_index(os);
dbb* deebeebee = reinterpret_cast<dbb*>(os.pword(index));
os << value.value() << "(" << deebeebee->value() << ")";
return os;
}
int main(int, char**)
{
dbb deebeebee(5);
dbb_reliant_type variable("blah");
std::cout << deebeebee << variable << std::endl;
return 0;
}
I'm not entirely sure if I understand what can be accessed at what time and what can and can't change, but....can you do something like this
struct TilewireFormatter {
DDB *ddb;
TilewireFormatter(DDB* d) : ddb(d) {}
print(std::ostream& out, const Tilewire& obj) {
// some formatting dependent on ddb
out << obj;
}
};
and replace out << tw; with formatter.print(out, tw);
then not provide any sort of << operator overload for Tilewire and pass an instance of TilewireFormatter around that's used to format them based on what ddb is?
I'm new at this, so in case providing my own answer gets in the way of me sharing the credit with Gary, well, Gary pointed out what I had just stumbled upon moments before through the same reference: Stream Storage for Private Use: iword, pword, and xalloc
#include <iostream>
// statically request a storage spot that can be associated with any stream
const int iosDdbIndex = std::ios_base::xalloc();
class DDB {
public:
// give the stream a pointer to ourselves
void bless(std::ostream& os) { os.pword(iosDdbIndex) = this; }
// provide a function that the insertion operator can access
int getSomething(void) { return 50; }
};
class Tilewire {
friend std::ostream& operator<< (std::ostream& os, Tilewire tilewire);
// encapsulate a dummy value
int m;
public:
// construct the Tilewire
Tilewire(int m) : m(m) {}
};
std::ostream& operator<< (std::ostream& os, Tilewire tilewire) {
// look up the pointer to the DDB object
DDB* ddbPtr = (DDB*) os.pword(iosDdbIndex);
// insert normally, and prove that we can access the DDB object's methods
return os << "Tilewire(" << tilewire.m << ") with DDB param " << ddbPtr->getSomething();
}
int main (int argc, char * const argv[]) {
DDB ddb;
ddb.bless(std::cout);
std::cout << Tilewire(0) << std::endl;
return 0;
}
Rather than fudging around and trying to find a way to pass contextual information while using the insertion operator, I suggest you make something like a print method like choobablue suggests. It's a nice and simple solution and anything fancier is probably more trouble than it's worth.
I also find it odd that you choose iostreams for an embedded system. They're one of the most bloated parts of the C++ standard library (not just by implementation, but by design) and if you are working on an embedded system, you could just as well roll your own alternative of this (still based on the basic design of iostreams) and can probably do it just as quickly as trying to use iostream effectively and across multiple threads.