im having an issue with the ostream, I have written a very basic macro that should print out its parameters.
Please see example code below:
#define LOG Message(__FILE__, __LINE__,__func__)
class Message : public std::ostringstream
{
public:
Message(const char *param1, int param2, const char *param3)
{
*this<<param3<<"("<<param1<<":"<<param2<<")";
}
~Message()
{
*this<<endl;
cout<< rdbuf()->str();
}
};
int main()
{
int integer = 1;
string str = "XYZ";
LOG<<integer<<"DEBUGLOG1: "<<str<<" "<<integer;
return 0;
}
The problem is if I use:
LOG << "LOG1: " << str << " " << integer;
The output prints the Address* of the const char* "LOG1: " rather than the value.
But,
If I use:
LOG << integer << "DEBUGLOG1: " << str << " " << integer;
The output works perfect, printing the integer value and the char value.
it looks like instead of using ostream& operator<< (ostream& out, const char* s );
it is using ostream& operator<< (const void* val); ?
Can anyone shed any light on what can be done to overcome this overloading please?
Thanks in advance
The problem is that Message(...) is a temporary. The temporary cannot bind to a non-const reference parameter for operator<<.
It can only be used with member functions and operators, like ostream::operator<<(int).
The odd thing is that the member operator returns a reference which can, in turn, be used with the non-member operators.
Precompile and see what the macro is getting unraveled as. Working with macros is difficult (and unadvisable...) and this is a very essentially debugging method you'll need to know to avoid keep reaching for Google or SO.
I believe you want g++ -E.
Related
I try to read a file decompress it and parse it to a tree in C++. Everything works fine with one excaption: For some reason I can construct a char[] string and use a pointer on it to output it with the help of cout inside a befriended overloaded <<-operator, but can't use the pointer returned by the operator to cout the string. I was thinking it might have to do with visibility of the string-memory, but that makes no sense to me since with "new" allocated memory should be visible to everyone since its on the heap of the program and not somekind of object or class heap. This all sounds rather confusing, let me show you a striped down version of the source and I'm pretty sure everything becomes clear (probably some really stupid mistake on my end... but I try since two days and don't find the mistake):
main:
#include "dekompstream.h"
#include <iostream>
int main(void) {
char *testString;
DekompStream ds(nullptr, 0);
std::cout << "TEST" << std::endl;
testString << ds;
std::cout << "Outside operator: " << testString << std::endl; // Fails misarably. Some weird randome memory-slice looking output
//delete [] testString;
return 0;
}
dekompstream.cpp:
#include "dekompstream.h"
DekompStream::DekompStream(uint8_t *kompDaten, unsigned int anzahlBytes) {
}
DekompStream::~DekompStream() {
}
uint8_t *DekompStream::dekompremieren() {
char *test = new char[4];
test[0] = 'A';
test[1] = 'B';
test[2] = 'C';
test[3] = '\0';
return (uint8_t *)test;
}
char *operator<<(char *zeichenkette, DekompStream &dekompStream) {
zeichenkette = (char *)dekompStream.dekompremieren();
std::cout << "Inside operator: " << zeichenkette << std::endl; // Works fine
return zeichenkette;
}
dekompstream.h:
#ifndef DEKOMPSTREAM_H
#define DEKOMPSTREAM_H
#include <cstdint>
#include <iostream>
class DekompStream {
public:
DekompStream(uint8_t *kompDaten, unsigned int anzahlBytes);
~DekompStream(void);
friend char *operator<<(char *zeichenkette, DekompStream &dekompStream);
private:
uint8_t *dekompremieren();
};
#endif
Thanks in advance :-)
testString << ds doesn't do what you think it does.
If we take a look at the code for operator<<:
char *operator<<(char *zeichenkette, DekompStream &dekompStream) {
zeichenkette = (char *)dekompStream.dekompremieren();
return zeichenkette;
}
The function reassigns the char* argument to a new value, then returns the new value. Fine. OK. But how does the compiler use this?
When we write:
testString << ds;
The compiler turns it into:
operator<<(testString, ds);
See the error?
You returned a new value, but because the operator overload was turned into a function call, the allocated pointer was lost. In addition, because the char* argument was simply reassigned, the original pointer value wasn't changed, meaning you got whatever was on the stack previously.
If we look at the declarations for the STL functions for iostream, we'll see the way to fix it:
ostream& operator<< (ostream& os, const char* s);
Notice the first parameter is passed by reference - this ensures any modifications to the stream made by the function persist in the calling context.
Simply change your function definition to:
char *operator<<(char *&zeichenkette, DekompStream &dekompStream){
...
}
and the issue will disappear.
I don't know why this is erroring, but I'm just trying to add something "akin" to endl so that I can throw what's in an ostringstream to our debugger. I have the following:
class debug_stream_info
{
public:
debug_stream_info(int errorLine, char *errorFile, int level)
:m_errorLine(errorLine), m_errorFile(errorFile), m_logLevel(level)
{
}
friend std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info);
private:
int m_errorLine;
std::string m_errorFile;
int m_logLevel;
};
std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info)
{
// Write the stream's contents to cpu_debug
// Deleted custom logging function. No errors here though
// Clear the stream for re-use.
os.str("");
os.seekp(0);
return os;
}
int main(int argc, char** argv)
{
std::ostringstream myout;
myout << "hey there" << " and some more " << "Numbers!!: " << 435 << 54.2 << " that's good for numbers" << debug_stream_info(__LINE__, __FILE__, LOG_LEVEL);
return 0;
}
The error I'm getting is: error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'debug_stream_info' (or there is no acceptable conversion) for the line in main. This is on VS2008.
I'm including sstream, iostream, etc, and have the namespaces set up right. I'm getting no other errors. I even tried replacing all occurrances of basic_ostream with just ostringstream and there was no difference (I'll be having a w_char version later, but I wanted the simple case to work first). I made the object on the line above and then passed a fully-constructed object on the line, and the error was exactly the same. I've changed the signature of the second argument to and from const with no change as well.
Any ideas on what I'm doing wrong here?
Edit: since EVERY response seems to want to put it there, I can NOT use std::ostream because I want this to work ONLY for std::ostringstream (and std::basic_ostringstream) and not for any type of output stream. Besides, the function wouldn't compile with ostream anyways, since I'm using the os.str() method, which isn't in ostream, only the sub-classes.
The real problem with your code is that you've overloaded std::ostringstream rather than std::ostream. So your code would work if you write this:
debug_stream_info info(/** blah blah**/);
std::ostringstream oss;
oss << info ; //OK
However this will not work:
oss << 1 << info; //ERROR
This is compilation error because the expression oss<<1 returns an object of type std::ostream& which doesn't have overload which takes debug_stream_info as second argument. That means if you use cast as:
static_cast<std::ostringstream&>(oss << 1) << info; //OK
then that should work again.
So the solution is to overload std::ostream, instead of std::basic_ostringstream.
Also, the second parameter should be const & . This is also a problem with your code.
So write this:
std::ostream& operator<<(std::ostream&, debug_stream_info const &);
//^^^^^^^ note this
The second parameter should be const & so that you could write temporary objects to the stream.
debug_stream_info(__LINE__, __FILE__, LOG_LEVEL); is creating unnamed object which is not returning anything hence error
#include <iostream>
#include <cstdio>
#include <sstream>
using namespace std;
class debug_stream_info
{
public:
debug_stream_info(int errorLine, char *errorFile, int level)
:m_errorLine(errorLine), m_errorFile(errorFile), m_logLevel(level)
{
}
friend std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info);
std::ostringstream& fun(std::ostringstream& os)
{
os<<"Ashish"<<endl;
return os;
}
private:
int m_errorLine;
std::string m_errorFile;
int m_logLevel;
};
std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info)
{
// Write the stream's contents to cpu_debug
// Deleted custom logging function. No errors here though
// Clear the stream for re-use.
// os.str("");
// os.seekp(0);
return os;
}
int main(int argc, char** argv)
{
std::ostringstream myout, test;
myout << "hey there" << " and some more " << "Numbers!!: " << 435 << 54.2 << " that's good for numbers"
<< debug_stream_info(1, "/home/ashish/test", 1).fun(test);
return 0;
}
Nawaz has explained very clearly why you're getting the error. The
usual solution in this case is to define your own stream type, unrelated
to std::istream. Something along the lines of:
class DebugStream
{
std::ostringstring* collector;
public:
template <typename T>
DebugStream& operator<<( T const& value )
{
if ( collector != NULL ) {
*collector << value;
}
return *this;
}
};
There are infinite variations on this; in your case, you could add a
non-template member function for your type; more likely, you'd add a
constructor which took the same arguments:
DebugStream( int lineNumber, std::string const& filename, int logLevel )
: collector( isActive( logLevel ) ? new std::ostringstream : NULL )
{
// Initial insertion of lineNumber, filename, timestamp...
}
You can also add a destructor which atomically flushes the collected
data to a file (or sends an email, or writes it to the system log, or
whatever). (Be very careful about this. You don't want an exception to
escape from the destructor, even if the logging fails.)
Finally, you might want to use a custom streambuf, rather than
stringstream. Say one that keeps the allocated buffer from one
instance to the next. And if you do this, rather than newing the
stream each time, you might pick up an instance from a table, indexed by
the log level (and initialized from a configuration file).
What I mean:
Everyone knows this method of redirecting stream to output:
cout << "sometext"
but is it possible to pass that stream to a function like this:
my_function() << "sometext";
Yes*:
#include <iostream>
#include <ostream>
std::ostream & my_function() { return std::cout; }
// ...
my_function() << "Hello world.\n";
*) Nothing you said in words is entirely correct, and you may well struggle later integrate this into your project, but this answer shows how to make your code do what you want.
Everyone knows this method of redirecting stream to output:
That's not what that does. The stream is called cout; that's the iostream object. The << operator does not redirect anything. The std::ostream objects all have overloaded operator<< functions. Those functions are invoked when you use << with a stream on the left-hand side and some type that has an overload for it on the right.
<< "sometext" is not a "stream" that can be "redirected". It isn't even a valid expression in C++. The << operator is binary. it takes two parameters.
my_function() << "sometext"; can only work if it returns a std::ostream class or something derived from it. Or something that has an overloaded operator<< defined for it and const char*.
cout << "sometext"
This is not "redirecting stream to output" it is invoking the operator << function on the cout object with the string literal "sometext"
if my_function() is returning a ostream which has operator << overloaded then my_function() << "sometext" will compile else it will give an error.
If you are looking for a way to overload << for your own function unrelated to streams, here is how you can do it:
struct MyStruct {
void DoSomething(const string& s);
};
MyStruct &operator<<(MyStruct &x, const string& s) {
x.DoSomething(s);
return x;
}
MyStruct& my_function() {
return MyStruct;
}
int main() {
my_function() << "Hello, world!";
}
In this example, DoSomething will be called on the instance of MyStruct returned from my_function, and "Hello, world!" will be passed to it as an argument.
If I understand what you are asking about, the closest equivalent of a shell redirect for a function that uses std::cout for output is probably to switch temporarily std::cout's internal stream buffer for a different one.
Of course, this is inherently not thread safe and won't cope if the function itself expects std::cout and stdout to be the same underlying thing.
#include <iostream>
#include <sstream>
int main()
{
std::stringbuf redir( std::ios_base::out );
std::streambuf* save = std::cout.rdbuf( &redir );
my_function(); // cout output ends up in redir
std::cout.rdbuf( save ); // restore original cout
}
I would like to be able to do:
foo(stringstream()<<"number = " << 500);
EDIT: single line solution is crucial since this is for logging purposes. These will be all around the code.
inside foo will print the string to screen or something of the sort.
now since stringstream's operator<< returns ostream&, foo's signature must be:
foo(ostream& o);
but how can I convert ostream& to string? (or char*).
Different approaches to achieving this use case are welcome as well.
The obvious solution is to use dynamic_cast in foo. But the given
code still won't work. (Your example will compile, but it won't do what
you think it should.) The expression std::ostringstream() is a
temporary, you can't initialize a non-const reference with a temporary,
and the first argument of std::operator<<( std::ostream&, char const*)
is a non-const reference. (You can call a member function on a
temporary. Like std::ostream::operator<<( void const* ). So the code
will compile, but it won't do what you expect.
You can work around this problem, using something like:
foo( std::ostringstream().flush() << "number = " << 500 );
std::ostream::flush() returns a non-const reference, so there are no
further problems. And on a freshly created stream, it is a no-op.
Still, I think you'll agree that it isn't the most elegant or intuitive
solution.
What I usually do in such cases is create a wrapper class, which
contains it's own std::ostringstream, and provides a templated
member operator<< which forwards to the contained
std::ostringstream. Your function foo would take a const
reference to this—or what I offen do is have the destructor call
foo directly, so that the client code doesn't even have to worry about
it; it does something like:
log() << "number = " << 500;
The function log() returns an instance of the wrapper class (but see
below), and the (final) destructor of this class calls your function
foo.
There is one slight problem with this. The return value may be copied,
and destructed immediately after the copy. Which will wreck havoc with
what I just explained; in fact, since std::ostringstream isn't
copyable, it won't even compile. The solution here is to put all of the
actual logic, including the instance of std::ostringstream and the
destructor logic calling foo in a separate implementation class, have
the public wrapper have a boost::shared_ptr to it, and forward. Or
just reimplement a bit of the shared pointer logic in your class:
class LogWrapper
{
std::ostringstream* collector;
int* useCount;
public:
LogWrapper()
: collector(new std::ostringstream)
, useCount(new int(1))
{
}
~LogWrapper()
{
-- *useCount;
if ( *useCount == 0 ) {
foo( collector->str() );
delete collector;
delete useCount;
}
}
template<typename T>
LogWrapper& operator<<( T const& value )
{
(*collector) << value;
return *this;
}
};
Note that it's easy to extend this to support optional logging; just
provide a constructor for the LogWrapper which sets collector to
NULL, and test for this in the operator<<.
EDITED:
One other thing occurs to me: you'll probably want to check whether the
destructor is being called as a result of an exception, and not call
foo in that case. Logically, I'd hope that the only exception you
might get is std::bad_alloc, but there will always be a user who
writes something like:
log() << a + b;
where the + is a user defined overload which throws.
I would suggest you to use this utility struct:
struct stringbuilder
{
std::stringstream ss;
template<typename T>
stringbuilder & operator << (const T &data)
{
ss << data;
return *this;
}
operator std::string() { return ss.str(); }
};
And use it as:
void f(const std::string & s );
int main()
{
char const *const pc = "hello";
f(stringbuilder() << '{' << pc << '}' );
//this is my most favorite line
std::string s = stringbuilder() << 25 << " is greater than " << 5 ;
}
Demo (with few more example) : http://ideone.com/J995r
More on my blog : Create string on the fly just in one line
You could use a proxy object for this; this is a bit of framework, but if you want to use this notation in a lot of places then it may be worth it:
#include <iostream>
#include <sstream>
static void foo( std::string const &s )
{
std::cout << s << std::endl;
}
struct StreamProxy
{
std::stringstream stream;
operator std::string() { return stream.str(); }
};
template <typename T>
StreamProxy &operator<<( StreamProxy &s, T v )
{
s.stream << v;
return s;
}
static StreamProxy make_stream()
{
return StreamProxy();
}
int main()
{
foo( make_stream() << "number = " << 500 );
}
This program prints
number = 500
The idea is to have a little wrapper class which can be implicitely converted into a std::string. The << operator is simply forwarded to the contained std::stringstream. The make_stream() function is strictly speaking not necessary (you could also say StreamProxy(), but I thought it looks a bit nicer.
A couple of options other than the nice proxy solution just presented by Frerich Raabe:
Define a static string stream variable in the header that defines the logging function and use the comma operator in your invocation of the logging function so that this variable is passed rather than the ostream& returned by the stream insertion operator. You can use a logging macro to hide this ugliness. The problem with this solution is that it is a bit on the ugly side, but this is a commonly used approach to logging.
Don't use C++ I/O. Use a varargs C-style solution instead. Pass a format string as the first argument, with the remaining arguments being targets for that format string. A problem with this solution is that even if your compiler is smart enough to ensure that printf and its cousins are safe, the compiler probably won't know that this new function is a part of the printf family. Nonetheless, this is also a commonly used approach.
If you don't mind using macros functions, you can make the logging function accept const string&, and use the following macro
#define build_string(expr) \
(static_cast<ostringstream*>(&(ostringstream().flush() << expr))->str())
And suppose you foo has signature void foo(const string&), you only need the one-liner
foo(build_string("number = " << 500))
This was inspired by James Kanze's answer about static_cast and stringstream.flush. Without the .flush() the above method fails with unexpected output.
Please note that this method should not leak memory, as temporary values, whether in the pointer form or not, are still allocated on the stack and hence destroyed upon return.
Since you're converting to string anyways, why not
void foo(const std::string& s)
{
std::cout << "foo: " << s << std::endl;
}
...
std::stringstream ss;
ss << "number = " << 500;
foo(ss.str());
This is not possible. As the name ostream implies, it is used for output, for writing to it. You could change the parameter to stringstream&. This class has the method str() which returns a std::string for your use.
EDIT I did not read the issue with operator << returning ostream&. So I guess you cannot simply write your statements within the functions argument list but have to write it before.
You can create a small wrapper around std::ostringstream that will convert back to std::string on use, and have the function take a std::string const &. The first approach to this solution can be found in this answer to a different question.
On top of that, you can add support for manipulators (std::hex) if needed.
I'm creating a logger with the following sections:
// #define LOG(x) // for release mode
#define LOG(x) log(x)
log(const string& str);
log(const ostream& str);
With the idea to do:
LOG("Test");
LOG(string("Testing") + " 123");
stringstream s;
LOG(s << "Testing" << 1 << "two" << 3);
This all works as intended, but when I do:
LOG(stringstream() << "Testing" << 1 << "two" << 3);
It does not work:
void log(const ostream& os)
{
std::streambuf* buf = os.rdbuf();
if( buf && typeid(*buf) == typeid(std::stringbuf) )
{
const std::string& format = dynamic_cast<std::stringbuf&>(*buf).str();
cout << format << endl;
}
}
results in 'format' containing junk data instead of the usual correct string.
I think this is because the temporary ostream returned by the << operator outlives the stringstream it comes from.
Or am I wrong?
(Why does string() work in this way? Is it because it returns a reference to itself? I'm assuming yes.)
I would really like to do it this way as I would be eliminating an additional allocation when logging in release mode.
Any pointers or tricks to get it done this way would be welcomed. In my actual solution I have many different log functions and they are all more complex than this. So I would prefer to have this implemented somehow in the calling code. (And not by modifying my #define if possible)
Just to give an idea, an example of one of my actual #defines:
#define LOG_DEBUG_MSG(format, ...) \
LogMessage(DEBUG_TYPE, const char* filepos, sizeof( __QUOTE__( #__VA_ARGS__ )), \
format, __VA_ARGS__)
which matches varargs printf-like log functions taking char*, string() and ostream() as well as non-vararg functions taking string(), exception() and HRESULT.
I think I see what's happening. This produces the expected output:
log(std::stringstream() << 1 << "hello");
while this does not:
log(std::stringstream() << "hello" << 1);
(it writes a hex number, followed by the "1" digit)
A few elements for the explanation:
An rvalue cannot be bound to a non-const reference
It is OK to invoke member functions on a temporary
std::ostream has a member operator<<(void*)
std::ostream has a member operator<<(int)
For char* the operator is not a member, it is operator<<(std::ostream&, const char*)
In the code above, std::stringstream() creates a temporary (an rvalue). Its lifetime is not problematic, as it must last for the whole full expression it is declared into (i.e, until the call to log() returns).
In the first example, everything works ok because the member operator<<(int) is first called, and then the reference returned can be passed to operator<<(ostream&, const char*)
In the second example, operator<<(cannot be called with "std::stringstream()" as a 1st argument, as this would require it to be bound to a non-const reference. However, the member operator<<(void*) is ok, as it is a member.
By the way: Why not define the log() function as:
void log(const std::ostream& os)
{
std::cout << os.rdbuf() << std::endl;
}
Alter your LOG() macro to this:
#define LOG(x) do { std::stringstream s; s << x; log(s.str()); } while(0)
That will let you use the following syntax in your debugging logs, so you don't have to manually construct the string stream.
LOG("Testing" << 1 << "two" << 3);
Then define it to nothing for release, and you'll have no extra allocations.