C++ passing stream to a class method - c++

i'm trying to write a logging class where you will be able to do something like this
//Create an instance of a class
Log log;
log.debug() << "a string " << 42 << endl;
log.info() << "another string " << 41 << endl;
This will produce the following output to stdout
Info: a string 42
Debug: another string 41
Here is what i have been able to achieve so far
#include <iostream>
#include <string>
#include <sstream>
#define endl '\n'
using std::cout;
using std::string;
using std::stringstream;
class Log {
public:
Log () {}
~Log() {}
//Create buffer to store everything
stringstream buffer;
//Create templase class to overload <<
template <class T>
inline Log & operator << (T data) {
buffer << data;
return *this;
}
inline Log & debug() {
print("Debug: ");
}
inline Log & info() {
print("Info: ");
}
inline void print(string type) {
//Display the contents of the buffer to standard output
cout << type << buffer.str();
//Clear the buffer
buffer.str(string());
}
};
int main() {
Log log;
log << "Hello " << "World " << 5 << " " << 2.3 << endl;
log.debug();
log << "Hello Again " << 42 << endl;
log.info();
return 0;
}
This produces the correct output but this way each line of logging takes up two lines of code and is very cumbersome. Can anyone thing off a way I can do log.debug() << "stuff"? This is a very simple example, in later versions, instead of just a string there will be time stamps, date stamps, usernames etc. which is why i'm trying to get each log level handled by a different function.
I am guessing I'll need another operator overload statement but i just can't figure out what it needs to be. Also the current << template operator doesn't like std::endl (wont compile if i use it) so I just set endl = '\n' at the top.
Thanks in advance, looking forward to learning as much as possible.

It sounds like what you want is for your debug and info functions to return something like a std::stringstream that will support operator<<, but somehow also flush the output afterwards. If that's it, you would be better off using something like a variadic template function.
As for your other issue, std::endl is actually a template, so its type cannot be used as T for Log::operator<< <T> (T). This is one example of why it's not worth trying to reimplement the stream functionality. The overload which lets you write << std::endl is declared something like template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits> & operator<<(basic_ostream<_CharT, _Traits>&, basic_ostream<_CharT, _Traits> &(basic_ostream<_CharT, _Traits> &)). std::endl is a function template which takes an ostream, appends a newline, and flushes the stream.
I should also note that your debug and info functions are not returning a value. If you're using GCC, the warning for this is disabled by default but it can be a very tricky source of undefined behavior. Use -Wreturn-type to enable it when you build something important.

Related

C++ Difference between inline anonymous instances and named instances

In a logging context, I would like to use a temporary instance of a utility class to collect some output, and use the destructor to dispose of the collected output. For example, printing to standard output as below.
I am noticing behavior differences depending whether the utility instance is constructed as an inline, anonymous instance as compared with a named automatic instance.
The named instances result in expected behavior and output. The inline instances have difficulty with the first insertion operation, apparently only working on operands which have simple conversions to int.
What is the difference between instances used in these different ways?
#include <string>
#include <sstream>
#include <iostream>
class Util
{
public:
std::ostringstream m_os;
Util() {}
~Util() { std::cout << m_os.str() << std::endl;}
};
int main (void)
{
// ----------- Using temporary anonymous instance -
// Output does not match expected, and the first insertion seems to
// only be able to handle instances that can be converted to int.
// Following prints "97key=val", but expect "akey=val"
(Util()).m_os << char('a') << std::string("key") << "=" << std::string("val");
// Following prints "0x80491eakey=val", but expect "Plain old C string key=val"
(Util()).m_os << "Plain old C string " << std::string("key") << "=" << std::string("val");
// Following results in syntax error
// error: no match for ‘operator<<’ in ‘Util().Util::m_os <<
(Util()).m_os << std::string("key") << "=" << std::string("val");
// ----------- Using named instance - output matches expected
// Block results in print "akey=val"
{
Util inst;
inst.m_os << char('a') << std::string("key") << "=" << std::string("val");
}
// Block results in print "Plain old C string key=val"
{
Util inst;
inst.m_os << "Plain old C string " << std::string("key") << "=" << std::string("val");
}
// Block results in print "key=val"
{
Util inst;
inst.m_os << std::string("key") << "=" << std::string("val");
}
return 0;
}
(Util()) creates a temporary object. As a result, (Util()).m_os is also a temporary object.
There are some definitions of operator<< as a member function, and some other definitions of it as a freestanding function. The former work on temporary objects, the latter does not, because a temporary cannot be bound to a reference-to-stream. Simplifying your code to a full example:
#include <stdio.h>
struct stream
{
stream& operator<<(int)
{ puts("operator<<(int)"); return *this; }
};
stream& operator<<(stream& s, char)
{ puts("operator<<(char)"); return s; }
struct streamwrapper
{
stream s;
};
int main()
{
streamwrapper w;
w.s << 'a'; // outputs operator<<(char)
streamwrapper().s << 'a'; // outputs operator<<(int)
}
Since the overloads you expected are unavailable, yet others are not, those other overloads get used instead of giving you a hard compiler error.

The first string argument to a stringstream is saved as a pointer/garbage [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Printing a string to a temporary stream object in C++
std::ostringstream printing the address of the c-string instead of its content
I'm trying to build up a string using stringstream, in the same way you'd use cout. This for something like a logging class. The issue I'm having is that if the first argument to the << operator is a string, when I subsequently print out that stringstream with the stringstream::str() call, I get a garbage address, and not the string. This only occurs with the FIRST string. Subsequent strings are fine. Numbers are always fine. Here's the code:
// class I use to print out the stream
class StreamWriter
{
public:
StreamWriter()
{}
~StreamWriter()
{
std::string myMessage = m_stringstream.str();
std::cout << myMessage << std::endl;
}
std::stringstream m_stringstream;
};
// macro for simplification
#define OSRDEBUG (StreamWriter().m_stringstream)
// actual use
OSRDEBUG << "Hello " << "my " << "name is Pris " << 123456;
// output
0x8054480my name is Pris 123456
0x8054480my name is Pris 123456
0x8054480my name is Pris 123456
0x8054480my name is Pris 123456
Could anyone shed some light on what's going on, and how I could get around the issue?
EDIT:
The following changes (in addition to padiablo's examples) works as well, maintaining the use of the class's destructor with the macro.
// class I use to print out the stream
class StreamWriter
{
public:
StreamWriter()
{ m_stringstream = new std::stringstream; }
~StreamWriter()
{
std::string myMessage = m_stringstream.str();
std::cout << myMessage << std::endl;
delete m_stringstream;
}
std::stringstream * m_stringstream;
};
// macro for simplication
#define OSRDEBUG *(StreamWriter().m_stringstream)
The original question still stands though, because it looks like it should work... and I think it's probably important to know when the times comes to put this into production-quality code.
The problem is indeed that the stream is a temporary.
Before C++11, there was no non-member operator<< overload that took an rvalue reference as the first parameter (aka, allowing writes to temporary streams).
As such, the only valid operator<< overloads were the members, since all non-member overloads take a non-const reference and as such will not bind to temporaries. One of those non-member overloads is the one responsible for printing C strings (aka char const*). Here's one of the member overloads:
basic_ostream<Ch, Traits>& operator<<(void* p);
And guess what your string literal liberally converts to. :)
After the first string, you get a normal reference back from the call to operator<<, which will then allow the non-member overloads to be viable.
I honestly don't understand exactly what's going on (it has something to do with your StreamWriter instance being a temporary), but I see the same effect as paxdiablo described in both GCC and MSVC.
However, here's something that can work around the problem. Add the following helper to your StreamWriter class:
ostream& get_ostream() {
return m_stringstream;
}
and change the macro to:
#define OSRDEBUG (StreamWriter().get_ostream())
I have tried a couple of alternatives, and the only thing I got working is something like this:
#define OSRDEBUG(s) \
do \
{ \
StreamWriter writer; \
writer.m_stringstream << s; \
} while (0)
OSRDEBUG("Hello " << "my " << "name is Pris " << 123456);
I have personally used the above construct for my own logging solutions many times, and seen it done by others as well.
I'm not good enough to know why your example doesn't work, but I guess it has something to do with temporaries not staying alive long enough.
It appears to be a consequence of the way you're instantiating the object. I'm still investigating (and you may get a better answer in the meantime) but explicitly instantiating the object works fine:
#include <iostream>
#include <sstream>
class StreamWriter {
public:
StreamWriter() {}
~StreamWriter() { std::cout << m_stringstream.str() << std::endl; }
std::stringstream m_stringstream;
};
int main (void) {
StreamWriter *sw = new StreamWriter();
sw->m_stringstream << "Hello " << "my " << "name is Pris ";
delete sw;
return 0;
}
As does instantiating on the stack as well:
int main (void) {
StreamWriter sw;
sw.m_stringstream << "Hello " << "my " << "name is Pris ";
return 0;
}
Both of those print out what you expect but the following simplification of your code does not:
int main (void) {
StreamWriter().m_stringstream << "Hello " << "my " << "name is Pris ";
return 0;
}
If you're just after a solution, you can probably get by with:
#define ORSDEBUG StreamWriter sw; sw.m_stringstream
and ensuring you scope-protect the command so that it doesn't try to create more then one sw, and also that it's destroyed at the correct time, same as your original attempt:
{ ORSDEBUG << "Hello " << "my " << "name is Pris"; }

QDebug-like structure: determine end of input via `operator<<`

Qt has a nice debug feature, called like that
qDebug() << first_qobject << second_qobject;
it produces a line with some "standard to-string" of the objects and -- and that's the important part -- prints a \n and flushed the steam after second_object. I want to reproduce that behaviour by a convention that all of my classes have a std::string to_string() method which I call:
struct myDebug{
template<typename T>
myDebug& operator<<(T t){
std::cout << t.to_string() << " "; // space-separated
return *this;
}
};
struct Point{
std::string to_string(){ return "42"; }
};
myDebug() << Point() << Point(); // should produce "42 42" plus a newline (which it doesn't)
My question is now: Is there a way to find out that after returning *this the second time the returned object is not called any more? So that I can then print the std::endl? qDebug() seems to be able to do that.
Found the solution and found out that my question is also a duplicate:
How does QDebug() << stuff; add a newline automatically?
In short, this can be done by implementing the destructor and just create temporary MyDebug objects like I did it in the code above and qDebug does it:
MyDebug() << foo << bar;
// will be destroyed after passing bar, and in the destructor I can now flush.

Overload handling of std::endl?

I want to define a class MyStream so that:
MyStream myStream;
myStream << 1 << 2 << 3 << std::endl << 5 << 6 << std::endl << 7 << 8 << std::endl;
gives output
[blah]123
[blah]56
[blah]78
Basically, I want a "[blah]" inserted at the front, then inserted after every non terminating std::endl?
The difficulty here is NOT the logic management, but detecting and overloading the handling of std::endl. Is there an elegant way to do this?
Thanks!
EDIT: I don't need advice on logic management. I need to know how to detect/overload printing of std::endl.
What you need to do is write your own stream buffer: When the stream buffer is flushed you output you prefix characters and the content of the stream.
The following works because std::endl causes the following.
Add '\n' to the stream.
Calls flush() on the stream
This calls pubsync() on the stream buffer.
This calls the virtual method sync()
Override this virtual method to do the work you want.
#include <iostream>
#include <sstream>
class MyStream: public std::ostream
{
// Write a stream buffer that prefixes each line with Plop
class MyStreamBuf: public std::stringbuf
{
std::ostream& output;
public:
MyStreamBuf(std::ostream& str)
:output(str)
{}
~MyStreamBuf() {
if (pbase() != pptr()) {
putOutput();
}
}
// When we sync the stream with the output.
// 1) Output Plop then the buffer
// 2) Reset the buffer
// 3) flush the actual output stream we are using.
virtual int sync() {
putOutput();
return 0;
}
void putOutput() {
// Called by destructor.
// destructor can not call virtual methods.
output << "[blah]" << str();
str("");
output.flush();
}
};
// My Stream just uses a version of my special buffer
MyStreamBuf buffer;
public:
MyStream(std::ostream& str)
:std::ostream(&buffer)
,buffer(str)
{
}
};
int main()
{
MyStream myStream(std::cout);
myStream << 1 << 2 << 3 << std::endl << 5 << 6 << std::endl << 7 << 8 << std::endl;
}
> ./a.out
[blah]123
[blah]56
[blah]78
>
Your overloaded operators of the MyStream class have to set a previous-printed-token-was-endl flag.
Then, if the next object is printed, the [blah] can be inserted in front of it.
std::endl is a function taking and returning a reference to std::ostream. To detect it was shifted into your stream, you have to overload the operator<< between your type and such a function:
MyStream& operator<<( std::ostream&(*f)(std::ostream&) )
{
std::cout << f;
if( f == std::endl )
{
_lastTokenWasEndl = true;
}
return *this;
}
Agreed with Neil on principle.
You want to change the behavior of the buffer, because that is the only way to extend iostreams. endl does this:
flush(__os.put(__os.widen('\n')));
widen returns a single character, so you can't put your string in there. put calls putc which is not a virtual function and only occasionally hooks to overflow. You can intercept at flush, which calls the buffer's sync. You would need to intercept and change all newline characters as they are overflowed or manually synced and convert them to your string.
Designing an override buffer class is troublesome because basic_streambuf expects direct access to its buffer memory. This prevents you from easily passing I/O requests to a preexisting basic_streambuf. You need to go out on a limb and suppose you know the stream buffer class, and derive from it. (cin and cout are not guaranteed to use basic_filebuf, far as I can tell.) Then, just add virtual overflow and sync. (See §27.5.2.4.5/3 and 27.5.2.4.2/7.) Performing the substitution may require additional space so be careful to allocate that ahead of time.
- OR -
Just declare a new endl in your own namespace, or better, a manipulator which isn't called endl at all!
I use function pointers. It sounds terrifying to people who aren't used to C, but it's a lot more efficient in most cases. Here's an example:
#include <iostream>
class Foo
{
public:
Foo& operator<<(const char* str) { std::cout << str; return *this; }
// If your compiler allows it, you can omit the "fun" from *fun below. It'll make it an anonymous parameter, though...
Foo& operator<<(std::ostream& (*fun)(std::ostream&)) { std::cout << std::endl; }
} foo;
int main(int argc,char **argv)
{
foo << "This is a test!" << std::endl;
return 0;
}
If you really want to you can check for the address of endl to confirm that you aren't getting some OTHER void/void function, but I don't think it's worth it in most cases. I hope that helps.
Instead of attempting to modify the behavior of std::endl, you should probably create a filtering streambuf to do the job. James Kanze has an example showing how to insert a timestamp at the beginning of each output line. It should require only minor modification to change that to whatever prefix you want on each line.
I had the same question, and I thought that Potatoswatter's second answer had merit: "Just declare a new endl in your own namespace, or better, a manipulator which isn't called endl at all!"
So I found out how to write a custom manipulator which is not hard at all:
#include <sstream>
#include <iostream>
class log_t : public std::ostringstream
{
public:
};
std::ostream& custom_endl(std::ostream& out)
{
log_t *log = dynamic_cast<log_t*>(&out);
if (log)
{
std::cout << "custom endl succeeded.\n";
}
out << std::endl;
return out;
}
std::ostream& custom_flush(std::ostream& out)
{
log_t *log = dynamic_cast<log_t*>(&out);
if (log)
{
std::cout << "custom flush succeeded.\n";
}
out << std::flush;
return out;
}
int main(int argc, char **argv)
{
log_t log;
log << "custom endl test" << custom_endl;
log << "custom flush test" << custom_flush;
std::cout << "Contents of log:\n" << log.str() << std::endl;
}
Here's the output:
custom endl succeeded.
custom flush succeeded.
Contents of log:
custom endl test
custom flush test
Here I've created two custom manipulators, one that handles endl and one that handles flush. You can add whatever processing you want to these two functions, since you have a pointer to the log_t object.
You can't change std::endl - as it's name suggests it is a part of the C++ Standard Library and its behaviour is fixed. You need to change the behaviour of the stream itself, when it receives an end of line . Personally, I would not have thought this worth the effort, but if you want to venture into this area I strongly recommend reading the book Standard C++ IOStreams & Locales.

How does QDebug() << stuff; add a newline automatically?

I'm trying to implement my own qDebug() style debug-output stream, this is basically what I have so far:
struct debug
{
#if defined(DEBUG)
template<typename T>
std::ostream& operator<<(T const& a) const
{
std::cout << a;
return std::cout;
}
#else
template<typename T>
debug const& operator<<(T const&) const
{
return *this;
}
/* must handle manipulators (endl) separately:
* manipulators are functions that take a stream& as argument and return a
* stream&
*/
debug const& operator<<(std::ostream& (*manip)(std::ostream&)) const
{
// do nothing with the manipulator
return *this;
}
#endif
};
Typical usage:
debug() << "stuff" << "more stuff" << std::endl;
But I'd like not to have to add std::endl;
My question is basically, how can I tell when the return type of operator<< isn't going to be used by another operator<< (and so append endl)?
The only way I can think of to achieve anything like this would be to create a list of things to print with associated with each temporary object created by qDebug(), then to print everything, along with trailing newline (and I could do clever things like inserting spaces) in ~debug(), but obviously this is not ideal since I don't have a guarantee that the temporary object is going to be destroyed until the end of the scope (or do I?).
Something like this will do:
struct debug {
debug() {
}
~debug() {
std::cerr << m_SS.str() << std::endl;
}
public:
// accepts just about anything
template<class T>
debug &operator<<(const T &x) {
m_SS << x;
return *this;
}
private:
std::ostringstream m_SS;
};
Which should let you do things like this:
debug() << "hello world";
I've used a pattern like this combined with a lock to provide a stream like logging system which can guarantee that log entries are written atomically.
NOTE: untested code, but should work :-)
Qt uses a method similar to #Evan. See a version of qdebug.h for the implementation details, but they stream everything to an underlying text stream, and then flush the stream and an end-line on destruction of the temporary QDebug object returned by qDebug().
When you write that this is the typical usage:
debug() << "stuff" << "more stuff" << std::endl;
are you definitely planning to construct a debug object each time you use it? If so, you should be able to get the behavior you want by having the debug destructor add the newline:
~debug()
{
*this << std::endl;
... the rest of your destructor ...
}
That does mean you cannot do something like this:
// this won't output "line1" and "line2" on separate lines
debug d;
d << "line1";
d << "line2";
The stream insertion (<<) and extraction (>>) are supposed to be non-members.
My question is basically, how can I
tell when the return type of
operator<< isn't going to be used by
another operator<< (and so append
endl)?
You cannot. Create a member function to specially append this or append an endl once those chained calls are done with. Document your class well so that the clients know how to use it. That's your best bet.