This question already has answers here:
Standard no-op output stream
(6 answers)
Closed 2 years ago.
I'd like to send data to nowhere, I mean that I don't want to print data in console nor in file, but I need some std::ostream object. How to do that?
I've used:
std::ostream bitBucket(0);
recently without problems, although it was flagged as having some potential problems if you looked at it from a certain angle (see the link below).
Aside: From what I understand (and I'm not entirely sure of this), that call above eventually ends up calling basic_ios::init(0) and, because that's a NULL pointer being passed in, it sets the stream state, as returned by the rdstate() function, to the badbit value.
This in turn prevents the stream from outputting any more information, instead just tossing it away.
The following program shows it in action:
#include <iostream>
int main (void) {
std::ostream bitBucket(0);
bitBucket << "Hello, there!" << std::endl;
return 0;
}
The page where I got it from also had this as a probably-cleaner solution (slightly modified to remove the duplication of my first solution above):
#include <iostream>
class null_out_buf : public std::streambuf {
public:
virtual std::streamsize xsputn (const char * s, std::streamsize n) {
return n;
}
virtual int overflow (int c) {
return 1;
}
};
class null_out_stream : public std::ostream {
public:
null_out_stream() : std::ostream (&buf) {}
private:
null_out_buf buf;
};
null_out_stream cnul; // My null stream.
int main (void) {
std::cout << std::boolalpha;
//testing nul
std::cout << "Nul stream before: " << cnul.fail() << std::endl;
cnul << "Goodbye World!" << std::endl;
std::cout << "Nul stream after: " << cnul.fail() << std::endl;
}
The simplest solution is just to output to an unopened std::ofstream
(or any other output stream in an error state). This will result in the
stream being permanently in an error state. This could be an advantage
(<< operators will skip the formatting), but if any code that you
can't control checks for errors, and does something particular if they
occur, you'll likely have problems.
Otherwise, it's pretty simple to implement a null stream; the only
streambuf function you really have to override is overflow.
Something like the following should do the trick:
class NulStreambuf : public std::streambuf
{
char dummyBuffer[64];
protected:
virtual int overflow( int c )
{
setp( dummyBuffer, dummyBuffer + sizeof( dummyBuffer ) ) ;
return (c == EOF) ? '\0' : c ;
}
};
(The buffer will avoid some unnecessary virtual function calls. On some
platforms, this makes a significant difference.)
Then create an output stream which uses it:
class NulOStream : public NulStreambuf, public std::ostream
{
public:
NulOStream() : std::ostream( this ) {}
};
(The use of inheritance, rather than containment, ensures that the
streambuf is fully constructed before being passed to the ostream.
This generally isn't necessary in practice, but the standard doesn't
seem to authorize passing a not yet constructed streambuf to the
constructor of ostream.)
Simplest solution: Use a std::stringstream.
#include <sstream>
#include <iostream>
void func(std::ostream& o){
o << "blatest\n";
}
int main(){
std::stringstream black_hole;
func(std::cout);
func(black_hole);
}
The stringstream will contain the output, but if you don't use it, it's the same as if it was never filled.
Since nobody mentioned it, if it's about suppressing std or error output, you can simply close the corresponding file descriptors (e.g. fclose (stdout) or fclose (stderr)).
That will shup up everything, including things like printf or fprintf (stderr, ...)
So you will indeed keep using the usual cout or cerr, but they will be turned into bit buckets.
Some suggestions here: http://bytes.com/topic/c/answers/589209-std-null-stream
A good answer from that site:
Use ordinary std::fstream, open it only for writing to required file
"/dev/null". It should work.
If you really want to create own stream, just derive it from
basic_ostream and simply define your own operator<< to be function
which only returns stream reference. You will have to write dummy
'write' and 'put' method too (and all other methods for output).
#include <streambuf>
#include <ostream>
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
From http://bytes.com/topic/c/answers/428285-null-ostream
Related
I've got a template class derived from std::basic_stringstream<typename TString::value_type...>, as you can see. The problem happens while trying to convert them. It's probably an obvious problem, though I cannot seem to figure out the solution.
As example in main, I have a simple std::wstring and initialize it with L"123".
After the std::wstring has been constructed, the operator of the custom basic_stringstream class is called (depending on std::wstring or std::string).
Inspecting the WCStringStream object for debugging purposes, shows that it contains - instead of the string L"123", the address of the first element of the entered string. The functions to_bytes and from_bytes do return the correct converted string, so the only problem left is the operator being called in both operator-functions:
*this << std::wstring_convert<...>().xx_bytes(s);
Example:
Template class is std::wstring.
Input is a std::string.
&operator<<(const std::string &s) is being called.
String is converted.
&operator<<(const std::wstring &s) is being called.
String-type matches with template type.
Operator of base-class (basic_stringstream) is called. (Or std::operator...)
Result:
Inspecting: {_Stringbuffer={_Seekhigh=0x007f6808 L"003BF76C췍췍췍췍췍췍췍췍췍...}...}
WCStringStream<std::wstring>::str() -> "003BF76C"
Expected result:
"123"
What's going wrong here ?
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <codecvt>
template<class TString>
class WCStringStream : public std::basic_stringstream<typename TString::value_type,
std::char_traits<typename TString::value_type>,
std::allocator<typename TString::value_type> >
{
typedef typename TString::value_type CharTraits;
typedef std::basic_stringstream<CharTraits, std::char_traits<CharTraits>, std::allocator<CharTraits> > MyStream;
//more typedefs...
public:
//Constructor...
inline WCStringStream(void) { }
inline WCStringStream(const TString &s) : MyStream(s) { }
//and more...
//operator>> overloads...
//defines for VS2010/2015 (C++11) included
inline WCStringStream &operator<<(const std::wstring &s)
{
if (typeid(TString) == typeid(s))
MyStream::operator<<(s.c_str());
else
*this << std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().to_bytes(s);
return *this;
}
inline WCStringStream &operator<<(const std::string &s)
{
if (typeid(TString) == typeid(s))
MyStream::operator<<(s.c_str());
else
*this << std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(s);
return *this;
}
};
//Example main
int main(int argc, char *argv[])
{
typedef std::wstring fstring;
WCStringStream<std::wstring> ws;
WCStringStream<std::string> ss;
ws << fstring(L"123");
int a = 0;
ws >> a;
std::cout << a << std::endl;
ss << fstring(L"123");
int b = 0;
ss >> b;
std::cout << b << std::endl;
return 0;
}
I'm compiling currently in VS2015 but I'd need it to run on VS2010 too.
First off: I think the approach to overload formatting function in a base class is ill-advised and I strongly recommend to not do it! I do realize that any alternative will require a bit more work.
In fact, I think your primary problem is actually that you do not reach your overloaded functions anyway just showing how fragile the approach is (I think the string describe what overload ends up being called but I haven't verified that these are indeed accurate, partly because the code provided in the question is lacking necessary context):
WCStringStream<std::string> stream;
stream << "calls std::operator<< (std::ostream&, char const*)\n";
stream << L"calls std::ostream::operator<< (void const*)\n";
stream << std::string("calls std::operator<< (std::ostream&, T&&)\n";
std::string const s("calls your operator\n");
stream << s;
Since the overloaded output operators for strings and string literals can't be changed and they do the wrong think with respect to code conversions, I recommend using an entirely different approach although it still won't be without peril(*): convert the strings explicitly although using a more nicely packaged version of the code than the standard provides.
Assuming always using char as character type for all uses I would use a function wcvt() which is called for all strings and string-literals when inserting them into a stream. Since at the point the function is being called it wouldn't know the type of the stream it is going to be used with, it would return essentially a reference to the character sequence which is then converted appropriately for the character type used for the stream. That would be something along these lines:
template <typename cT>
class wconvert {
cT const* begin_;
cT const* end_;
public:
wconvert(std::basic_string<cT> const& s)
: begin_(s.data())
, end_(s.data() + s.size()) {
}
wconvert(cT const* s)
: begin_(s)
, end_(s + std::char_traits<cT>::length(s)) {
}
cT const* begin() const { return this->begin_; }
cT const* end() const { return this->end_; }
std::streamsize size() const { return this->end_ - this->begin_; }
};
template <typename cT>
wconvert<cT> wcvt(cT const* s) {
return wconvert<cT>(s);
}
template <typename cT>
wconvert<cT> wcvt(std::basic_string<cT> const& s) {
return wconvert<cT>(s);
}
template <typename cT>
std::basic_ostream<cT>& operator<< (std::basic_ostream<cT>& out,
wconvert<cT> const& cvt) {
return out.write(cvt.begin(), cvt.size());
}
std::ostream& operator<< (std::ostream& out, wconvert<wchar_t> const& cvt) {
auto tmp = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().to_bytes(cvt.begin(), cvt.end());
return out.write(tmp.data(), tmp.size());
}
std::wostream& operator<< (std::wostream& out, wconvert<char> const& cvt) {
auto tmp = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(cvt.begin(), cvt.end());
return out.write(tmp.data(), tmp.size());
}
Of course, using this approach requires the use of wcvt(s) whenever s may be a string which needs to be converted. It is easy to forget doing so and it seems the original objective was to not have to remember the use of such a conversion. However, I don't see any alternative which is less fragile with the system of existing streams. Entirely abandoning the use of streams and using an entirely separate system of formatted I/O may yield less fragile approach.
(*) The approach easiest to get right is to stick with just on character type in a program and always using this character type. I do believe it was actually an error to introduce a second character type, wchar_t, and it an even bigger error to further complicate the existing mess by having also introduced char16_t and char32_t. We'd be much better off there were just one character type, char, although it actually wouldn't represent character but bytes of an encoding.
The problem was to explicitly call the base class operator, which takes the const void *_Val overload and prints the address.
MyStream::operator<<(s.c_str());
The solution to the problem:
if (typeid(TString) == typeid(s))
{
MyStream &os = *this;
os << s.c_str();
}
Of course calling *this << s.c_str() results in recursion, but the using the base class, it calls the global overloaded operator for the correct char-type wchar_t / char.
An also working solution is to use the member-function write instead of the operator.
How to implement ostream-like class from scratch using printf only?
For me looks like the problem is in choosing the format string ,which is actually equal to the identifying input`s type and treating precision
I assume you mean something that overloads operator<< by "an ostream-like class". It's easy to identify the type of the argument to a function just by having overloads. For example, you might have:
ostreamlike& ostreamlike::operator<<(int x)
{
printf("%d", x);
return *this;
}
ostreamlike& ostreamlike::operator<<(float x)
{
printf("%f", x);
return *this;
}
The format of the output is determined by whichever overload is picked.
Think, it could be something like that
#include <stdio.h>
class ostreamlike {
public:
ostreamlike(FILE* f_): f(f_) {}
ostreamlike& write(int n) {
fprintf(f, "%d", n);
return *this;
}
ostreamlike& write(const char* n) {
fprintf(f, "%s", n);
return *this;
}
private:
FILE* f;
};
// operator for types that is supported ostreamlike internally
template <typename type>
ostreamlike& operator<<(ostreamlike& stream, const type& data) {
return stream.write(data);
}
// external implementations to write using ostreamlike
ostreamlike& operator<<(ostreamlike& stream, bool data) {
return stream.write(data ? "true" : "false");
}
int main() {
ostreamlike s(stdout);
s << "hello " << 1 << " : " << true << "\n";
return 0;
}
It depends on how close to the real ostream you want to be. Assuming you want to do it properly you would also need a streambuf derived class. ostream only does the formatting, the actual I/O is done by an internal streambuf derived class. Since streambuf does unformatted I/O you would need to use fwrite not printf.
If your goal is just to do I/O on an already existing FILE* pointer this is the way to go. You derive one class from streambuf, say streambuf_with_FILE and then you derive another class from ostream say ostream_with_FILE. streambuf_with_FILE overrides the appropriate methods to do the actual I/O and ostream_with_FILE has an internal streambuf_with_FILE object. There's actually very little code required.
Is there a way to create an ostream instance which basically doesn't do anything ?
For example :
std::ostream dummyStream(...);
dummyStream << "Nothing will be printed";
I could just create an ostringstream, but data will be buffered (and I really don't want to make anything with them, so it adds a useless overhead).
Any idea ?
[edit] Found this related question which suits my needs. However, I think it could be useful to have a answer saying how to create a valid (no badbit) output stream with standard c++.
You need a custom streambuf.
class NullBuffer : public std::streambuf
{
public:
int overflow(int c) { return c; }
};
You can then use this buffer in any ostream class
NullBuffer null_buffer;
std::ostream null_stream(&null_buffer);
null_stream << "Nothing will be printed";
streambuf::overflow is the function called when the buffer has to output data to the actual destination of the stream. The NullBuffer class above does nothing when overflow is called so any stream using it will not produce any output.
If this is to disable logging output, your dummyStream would still cause arguments to be evaluated. If you want to minimize impact when logging is disabled, you can rely on a conditional, such as:
#define debugStream \
if (debug_disabled) {} \
else std::cerr
So if you have code like:
debugStream << "debugging output: " << foo() << std::endl;
No arguments will be evaluated if debug_disabled is true.
The basic method voor new stream classes is:
Derive a class from std::streambuf;
Override the virtual functions in that class. This is where the real work is done. In your case, empty implementations should be good enough.
Derive a class from std::ostream with one member, your streambuf class.
The constructor of your streamclass should forward the pointer to that member to the base constructor of std::ostream.
I'm afraid you won't get rid of the formatting step, though.
Hopefully this gives you some pointers; I don't have the time to expand this into a full answer, sorry.
Update: See john's answer for details.
For runtime-controllable redirection of log messages, a self-contained solution combining the ideas of john and Sjoerd:
class DebugStream {
private:
class NullStream : public std::ostream {
private:
class NullBuffer : public std::streambuf {
public:
int overflow(int c) override { return c; }
} buffer_;
public:
NullStream() : std::ostream(&buffer_) {}
} null_;
std::ostream &output_;
bool enabled_;
public:
DebugStream(std::ostream &output = std::cout) : output_(output), enabled_(false) {}
void enable(const bool enable) { enabled_ = enable; }
template <typename T> std::ostream& operator<<(const T &arg) {
if (enabled_) return output_ << arg;
else return null_ << arg;
}
};
extern DebugStream debug_stream;
#define TRACE_ENABLE(x) debug_stream.enable(x)
#define TRACELN(x) debug_stream << x << std::endl
#define TRACE(x) debug_stream << x
Then you can do stuff like:
TRACELN("The value of x is " << x " and the value of y is " << y);
It would also be easy to just remove the trace statements from a release version completely with #define the trace macros to empty statements.
You still need to define debug_stream somewhere global, though.
If you are concerned about the overhead of your debugger then you can write a very simple code to void out your debug messages on compilation. This is what I use for my c++ programs.
#include <iostream>
#define DEBUGGING // Define this in your config.h or not.
#ifdef DEBUGGING
/*
* replace std::cout with your stream , you don't need to
* worry about the context since macros are simply search
* and replace on compilation.
*/
#define LOG_START std::cout <<
#define LOG_REDIR <<
#define LOG_END << std::endl;
#else
#define LOG_START if(0){(void)
#define LOG_REDIR ;(void)
#define LOG_END ;}
#endif // DEBUGGING
int main(){
LOG_START "This is a log message " LOG_REDIR "Still a log message." LOG_END;
return 0;
}
Now when making your project , check if the user wants to disable the logging , if so , just undefine the DEBUGGING macro or whatever macro you choose to check for.
Now your code will be optimized by the compiler , Because when anything is voided , it will not be included in the resulting binary(most of the time) , making the binary production ready.
I needed a null stream that was of type ostream so I did something like this:
struct NullStream: public stringstream {
NullStream(): stringstream() {}
};
template<typename T>
void operator<<(const NullStream&, const T&) {}
Application code:
NullStream ns;
ostream &os = ns;
os << "foo";
The real issue is all the public methods that I inherited but don't care about so I just didn't bother overriding them.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
pure virtual function and abstract class
I have a class and I want to create a virtual function that will be used to print debug information. Any class that inherits this class will have to implement this virtual function. This way different classes could print the debug messages to different output devices such as std::cout, labels, files etc.
The base class won't be aware of the messages destination. But I don't know the best way to do this. I'm thinking of using something like printf() which can print an arbitrary number of parameters. But I don't know what that would be accomplished. Any ideas?
There is a disadvantage to the approach that you propose. Every derived class will have to implement a printf like facility themselves. That doesn't seem like a very productive activity, and it would make the base class very annoying to use.
It may be less burdensome, code wise, to have the base class require the derived classes provide a debug ostream. Or, you could default to cerr.
class Base {
protected:
virtual std::ostream & debug_stream () const { return std::cerr; }
//...
};
Then, an external user of Base can poke info into the debug_stream.
If you insist on printf style syntax, the interface could return a FILE * instead:
class Base {
protected:
virtual FILE * debug_file () const { return stderr; }
//...
};
So, for example, a derived class could do this:
class Derived : public Base {
static std::ofstream dbgstream;
std::ostream & debug_stream () const { return dbgstream; }
//...
};
std::ofstream Derived::dbgstream("/tmp/derived.dbg");
Then if one has proper access to the base class interface,
void foo (Base *b) {
//...do something with b
b->debug_stream()
<< __FILE__ << ":" << __LINE__ << " foo did something"
<< std::endl;
//...
}
I would do something like this:
class Base
{
protected:
virtual int doDebug(const std::string& Msg) const = 0;
public:
int Debug(const char* MsgFmt, ...) const;
};
int Base::Debug(const char* MsgFmt, ...) const
{
std::string sMsg;
va_list args;
va_start(args, MsgFmt);
int len = vsnprintf(NULL, 0, MsgFmt, args);
if (len > 0)
{
sMsg.resize(len);
vsnprintf(&sMsg[0], len + 1, MsgFmt, args);
}
va_end(args);
return doDebug(sMsg);
}
That way, you still provide the caller with flexible formatting, but the derived classes do not have to worry about that because they are given only pre-formatted text.
I would just do this
class Base
{
virtual int debugfn(const std::string& msg) const = 0;
};
I.e., don't mix the functionality of printf (producing a formatted string and sending it to stdout) with the debugging function. Let it take as its argument a string that is already complete, and let the derived classes decide what to do with it. The int can be an error code if desired, otherwise just return void.
The basic idea here is to use a protected virtual function that takes a string as the error/log/debug-message to be printed / logged. Then, your base class exposes a non-virtual function (or set of functions) to construct the string that will be fed to the protected virtual function. To actually create the string, you can use one of many ways, in the style of printf (with varargs or variadic templates (C++11)), or in the style of standard iostreams. Here is one solution in the latter category:
class BaseDebugOutput {
protected:
virtual void printMessage(const std::string& aMsg) = 0;
private:
std::stringstream temp_stream;
public:
virtual ~BaseDebugOutput() { };
// One << operator for any type.
template <typename T>
BaseDebugOutput& operator<<(const T& value) {
temp_stream << value;
return *this;
};
typedef std::basic_ostream< std::stringstream::char_type,
std::stringstream::traits_type >&
(*ostream_function_ptr)(
std::basic_ostream< std::stringstream::char_type,
std::stringstream::traits_type >&);
// One << operator for things like std::endl.
BaseDebugOutput& operator<<(ostream_function_ptr p) {
if(p == ostream_function_ptr(std::endl)) {
// if the user outputted an end-line, then print the entry:
temp_stream << std::endl;
std::string temp_msg;
std::getline(temp_stream,temp_msg);
// call the protected virtual function:
printMessage(temp_msg);
} else {
temp_stream << p;
};
return *this;
};
};
An example derived class would be:
class CErrDebugOutput : public BaseDebugOutput {
protected:
virtual void printMessage(const std::string& aMsg) {
std::cerr << "Error reported with message: '" << aMsg << "'." << std::endl;
};
};
And the use-case would look like this:
int main() {
BaseDebugOutput* debug_output = new CErrDebugOutput;
(*debug_output) << "The answer is: " << 42 << "!" << std::endl;
delete debug_output;
return;
};
One advantage of the above setup is that you can insert almost anything you want in addition to the error message, such as a time-stamp for example, or just adding the "Error: " string or whatever so that you don't have to repeat that all the time at the points where you issue the messages (call-site).
I might not have understood the question, because the simplest thing that comes to mind has not been offered in all the other answers... If the intention is providing a single entry point for all the hierarchy to print information, then this is the simplest approach:
class base {
public:
virtual std::ostream& print( std::ostream& /*...*/ ) const = 0;
};
std::ostream& operator<<( std::ostream& o, base const & b ) {
return b.print( o );
}
The comment /*...*/ is there because, unlike operator<< the signature is not fixed, so you could pass extra arguments to control the formatting (say, bool single_line, int indent --if !single_line to insert leading spaces, int verbosity to control whether only the public state of the object is to be printed or also auxiliary data...) to produce richer output.
With a single implementation (and a forwarding function) you get printing of the objects to a stream and a way of generating logs with the state of your program for debugging.
If on the other hand what you mean is a solution for derived classes to print debug messages regarding their state at different points in time, then you cannot really do that polymorphically, as the decision to log messages and when should be taken by the derived types. In that case, just pull a logging library and use it. Common logging libraries have very little cost at runtime if the log level is lower than the type of messages (i.e. if you configure to log only warning, the cost of the debug logs (that will not be generated) is very small.
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".