I'm working on a CGI application, which needs to send response headers, including Content-Length, before the body, but of course this is unknown until the body is fully formed. I could just use a string and concatenate as I go, but I like using the << operator as with cout, so I created this little class:
#include <iostream>
using namespace std;
class outbuf {
public:
void operator<<(const char *str) {
this->buffer+= str;
}
void operator<<(const string &str) {
this->buffer+= str;
}
void obsend() {
cout << this->buffer;
this->buffer.clear();
}
private:
string buffer;
};
int main(int argc, char **argv, char** envp) {
outbuf cbout;
string s = " of the output buffer.";
cbout << "This is ";
cbout << "a test" << " ...";
cbout << s;
cbout.obsend();
return 0;
}
The problem comes with cbout << "a test" << " ..."; On the second operator, the compiler complains invalid operands of types 'void' and 'const char [5]' to binary 'operator<<' I understand the error, but not sure what to do about it. Is there a better way to accomplish what I'm trying to do? This article looked promising, but I'm not able to understand some of what he's talking about, and it doesn't appear to exactly fit what I'm trying to do.
Your operator<< overload should simply return a reference to itself:
outbuf &operator<<(const char *str) {
// ...
return *this;
}
So now the result of the first << operator is the same object, against which the second, chained, << operator will happily use.
Change all your << operators to work this way.
Related
I have a small code snippet which tries to overload "<<" operator of std::cout.
#include<iostream>
using namespace std;
ostream& operator<<(ostream& out,const string& str)
{
out << "overloading" << str << "done";
return out;
}
int main()
{
cout << "string123";
}
output: string123.
It seems my overloading function is not being called. Why?
You're basically shooting yourself in the footin your example. You overload operator<< for std::string type, so you should expect it gets called every time you try to send an "std::string" to out, thus causing runtime stack overlow. To make it work, you:
need to output a char * type to out in operator<< overload, so it doesn't cause infinite recursion
send an actual std::string in main.
Here's a working example without runtime stack overflow problem:
#include<iostream>
using namespace std;
ostream& operator<<(ostream& out, const string& str)
{
out << "overloading" << str.c_str() << "done";
return out;
}
int main()
{
cout << std::string("string123");
}
The output is
overloadingstring123done
First of all, you're not streaming a std::string, but a const char*. You can fix that by writing cout << std::string("string123") instead (demo; although, ew).
Note that there is already such an overload in <string>, and your implementation apparently just go happens to include <string> through <iostream> (as does mine, and as is its prerogative). However, your version (after making the fix above) is a better match since ADL doesn't need to be invoked to find it.
You should send a string type to <<:
ostream& operator<<(ostream& out,const string& str)
{
out<<"overloading";
return out;
}
int main()
{
string s = "string123";
cout << s;
}
Note that sending again the string itself in the << definition will make infinite recursion for
out << "overloading" << str <<"done"
Is it possible to write a method that takes a stringstream and have it look something like this,
void method(string str)
void printStringStream( StringStream& ss)
{
method(ss.str());
}
And can be called like this
stringstream var;
printStringStream( var << "Text" << intVar << "More text"<<floatvar);
I looked up the << operator and it looks like it returns a ostream& object but I'm probably reading this wrong or just not implementing it right.
Really all I want is a clean way to concatenate stuff together as a string and pass it to a function. The cleanest thing I could find was a stringstream object but that still leaves much to be desired.
Notes:
I can't use much of c++11 answers because I'm running on Visual Studio 2010 (against my will, but still)
I have access to Boost so go nuts with that.
I wouldn't be against a custom method as long as it cleans up this mess.
Edit:
With #Mooing Duck's answer mixed with #PiotrNycz syntax I achieved my goal of written code like this,
try{
//code
}catch(exception e)
{
printStringStream( stringstream() << "An exception has occurred.\n"
<<" Error: " << e.message
<<"\n If this persists please contact "<< contactInfo
<<"\n Sorry for the inconvenience");
}
This is as clean and readable as I could have hoped for.
Hopefully this helps others clean up writing messages.
Ah, took me a minute. Since operator<< is a free function overloaded for all ostream types, it doesn't return a std::stringstream, it returns a std::ostream like you say.
void printStringStream(std::ostream& ss)
Now clearly, general ostreams don't have a .str() member, but they do have a magic way to copy one entire stream to another:
std::cout << ss.rdbuf();
Here's a link to the full code showing that it compiles and runs fine http://ideone.com/DgL5V
EDIT
If you really need a string in the function, I can think of a few solutions:
First, do the streaming seperately:
stringstream var;
var << "Text" << intVar << "More text"<<floatvar;
printStringStream(var);
Second: copy the stream to a string (possible performance issue)
void printStringStream( ostream& t)
{
std::stringstream ss;
ss << t.rdbuf();
method(ss.str());
}
Third: make the other function take a stream too
Make your wrapper over std::stringstream. In this new class you can define whatever operator << you need:
class SSB {
public:
operator std::stringstream& () { return ss; }
template <class T>
SSB& operator << (const T& v) { ss << v; return *this; }
template <class T>
SSB& operator << (const T* v) { ss << v; return *this; }
SSB& operator << (std::ostream& (*v)(std::ostream&)) { ss << v; return *this; }
// Be aware - I am not sure I cover all <<'s
private:
std::stringstream ss;
};
void print(std::stringstream& ss)
{
std::cout << ss.str() << std::endl;
}
int main() {
SSB ssb;
print (ssb << "Hello" << " world in " << 2012 << std::endl);
print (SSB() << "Hello" << " world in " << 2012 << std::endl);
}
For ease of writing objects that can be inserted into a stream, all these classes overload operator<< on ostream&. (Operator overloading can be used by subclasses, if no closer match exists.) These operator<< overloads all return ostream&.
What you can do is make the function take an ostream& and dynamic_cast<> it to stringstream&. If the wrong type is passed in, bad_cast is thrown.
void printStringStream(ostream& os) {
stringstream &ss = dynamic_cast<stringstream&>(os);
cout << ss.str();
}
Note: static_cast<> can be used, it will be faster, but not so bug proof in the case you passed something that is not a stringstream.
Since you know you've got a stringstream, just cast the return value:
stringstream var;
printStringStream(static_cast<stringstream&>(var << whatever));
Just to add to the mix: Personally, I would create a stream which calls whatever function I need to call upon destruction:
#include <sstream>
#include <iostream>
void someFunction(std::string const& value)
{
std::cout << "someFunction(" << value << ")\n";
}
void method(std::string const& value)
{
std::cout << "method(" << value << ")\n";
}
class FunctionStream
: private virtual std::stringbuf
, public std::ostream
{
public:
FunctionStream()
: std::ostream(this)
, d_function(&method)
{
}
FunctionStream(void (*function)(std::string const&))
: std::ostream(this)
, d_function(function)
{
}
~FunctionStream()
{
this->d_function(this->str());
}
private:
void (*d_function)(std::string const&);
};
int main(int ac, char* av[])
{
FunctionStream() << "Hello, world: " << ac;
FunctionStream(&someFunction) << "Goodbye, world: " << ac;
}
It is worth noting that the first object sent to the temporary has to be of a specific set of types, namely one of those, the class std::ostream knows about: Normally, the shift operator takes an std::ostream& as first argument but a temporary cannot be bound to this type. However, there are a number of member operators which, being a member, don't need to bind to a reference! If you want to use a user defined type first, you need to extract a reference temporary which can be done by using one of the member input operators.
#include <string>
#include <iostream>
template <typename T>
T max(T a, T b) {
return a > b ? a : b;
}
class Dummy {
private:
std::string name;
int age;
public:
Dummy(int an_age) {age = an_age;}
bool operator> (Dummy &a) {return age > a.age;}
std::string toString() const {return "The age is " + age;}
};
std::ostream& operator<<(std::ostream& out, const Dummy& d) {return out<< d.toString();}
int main()
{
std::cout << max(3, 7) << std::endl;
std::cout << max(3.0, 7.0) << std::endl;
std::cout << max<int>(3, 7.0) << std::endl;
std::cout << max("hello", "hi") << std::endl;
Dummy d1(10);
Dummy d2(20);
std::cout << max(&d1, &d2) << std::endl;
return 0;
}
I'm pretty new to C++ but not new to programming. I've written the code to play with template and operator overloading in C++.
It took quite a while to make it compile and partially work.
The ostream operator<< is not working properly, only to return the address of the object. I can't figure out the causes.
I managed to make it compile by blind trial and error, so I suspect the code might be broken to some extent. And I may not be aware of what'd be improved.
Your max(&d1,&d2) expression gives you the address, and that is printed out. Your operator overloading is fine.
I assume the line you're talking about is
std::cout << max(&d1, &d2) << std::endl;
The problem is you are passing Dummy * instead of Dummy. That makes max return Dummy *, and since your overloaded operator<< takes (essentially) Dummy, it isn't invoked. If you're trying to pass by reference, you don't need to do anything special on the caller side, just make the function take a reference and the compiler will figure it out.
Don't write your own max, use the standard one instead:
#include <algorithm>
void f() { int a = std::max(8, 4); }
The only difference is that the standard max uses operator < by default, just like everything else in the standard library.
Your toString function does something different from what you think it does. It instead returns the sub string of "The age is " starting at the character number age. For example if age is 3, toString will return " age is ". To convert the integer to string you have to use ostringstream:
std::string toString() const {
std::ostringstream s;
s << "The age is " << age;
return s.str();
}
If you hand any pointer to a C++ stream, it's address will be put into the output. (Obviously unless there's a more specific output handler.)
void* px = NULL;
const char* ps = "Test";
FooType* pf = ...;
stringstream s;
s << ps << " " << px << " " << pf "\n";
s.str(); // yields, for example: "Test 0 AF120089"
This can be a problem, if the user erroneously was trying to actually print the value of FooType.
And it is also a problem when mixing wide char and narrow char, because instead of a compiler error, you'll get the address printed:
const wchar_t* str = L"Test! (Wide)";
// ...
cout << str << "\n"; // Ooops! Prints address of str.
So I was wondering - since I very rarely want to output a pointer value, would it be possible to disable formatting of pointer values, so that inserting a pointer value into a stream would result in a compiler error? (Outputting of pointer values could then be easily achieved by using a wrapper type or casting the pointer values to size_t or somesuch.)
Edit: In light of Neil's answer (disabling void* output by providing my own void* output operator) I would like to add that it would be nice if this also worked for tools such as Boost.Format, that make implicit use of the output operator defined in the std namespace ...
This gives a compilation error in g++ if the second and/or third output to cout is uncommented:
#include <iostream>
using namespace std;
ostream & operator << ( const ostream &, void * ) {
}
int main() {
int n = 0;
cout << 0;
// cout << &n;
// cout << (void *) 0;
}
A global template version of operator<< seems to work:
#include <iostream>
#include <boost/static_assert.hpp>
template<typename T>
std::ostream & operator<<(std::ostream & stream, T* value) {
BOOST_STATIC_ASSERT(false);
}
int main() {
int foo = 5;
int * bar = &foo;
std::cout << bar << std::endl;
}
Edit: This solution does not work as intended, as the template also captures string literals. You should prefer #Neil's solution.
Yes, you can cause a compilation error by providing your own overload of ostream's operator <<.
#include <iostream>
template <typename T>
std::ostream& operator << (std::ostream& s, T* p)
{
char ASSERT_FAILED_CANNOT_OUTPUT_POINTER[sizeof(p) - sizeof(p)];
}
int main()
{
int x;
int* p = &x;
cout << p;
}
Keep the operator << unimplemented for pointers.
template<typename T>
std::ostream& operator<<(std::ostream &stream, T* value);
Edit: Or better to put an invalid typename to get compiler error.
Consider the following function:
void f(const char* str);
Suppose I want to generate a string using stringstream and pass it to this function. If I want to do it in one statement, I might try:
f((std::ostringstream() << "Value: " << 5).str().c_str()); // error
This gives an error: 'str()' is not a member of 'basic_ostream'. OK, so operator<< is returning ostream instead of ostringstream - how about casting it back to an ostringstream?
1) Is this cast safe?
f(static_cast<std::ostringstream&>(std::ostringstream() << "Value: " << 5).str().c_str()); // incorrect output
Now with this, it turns out for the operator<<("Value: ") call, it's actually calling ostream's operator<<(void*) and printing a hex address. This is wrong, I want the text.
2) Why does operator<< on the temporary std::ostringstream() call the ostream operator? Surely the temporary has a type of 'ostringstream' not 'ostream'?
I can cast the temporary to force the correct operator call too!
f(static_cast<std::ostringstream&>(static_cast<std::ostringstream&>(std::ostringstream()) << "Value: " << 5).str().c_str());
This appears to work and passes "Value: 5" to f().
3) Am I relying on undefined behavior now? The casts look unusual.
I'm aware the best alternative is something like this:
std::ostringstream ss;
ss << "Value: " << 5;
f(ss.str().c_str());
...but I'm interested in the behavior of doing it in one line. Suppose someone wanted to make a (dubious) macro:
#define make_temporary_cstr(x) (static_cast<std::ostringstream&>(static_cast<std::ostringstream&>(std::ostringstream()) << x).str().c_str())
// ...
f(make_temporary_cstr("Value: " << 5));
Would this function as expected?
You cannot cast the temporary stream to std::ostringstream&. It is ill-formed (the compiler must tell you that it is wrong). The following can do it, though:
f(static_cast<std::ostringstream&>(
std::ostringstream().seekp(0) << "Value: " << 5).str().c_str());
That of course is ugly. But it shows how it can work. seekp is a member function returning a std::ostream&. Would probably better to write this generally
template<typename T>
struct lval { T t; T &getlval() { return t; } };
f(static_cast<std::ostringstream&>(
lval<std::ostringstream>().getlval() << "Value: " << 5).str().c_str());
The reason that without anything it takes the void*, is because that operator<< is a member-function. The operator<< that takes a char const* is not.
A temporary cannot be passed as a non-const reference to a function, that's why it does not find the correct streaming operator and instead takes the one with void* argument (it is a member function and thus calling it on a temporary is OK).
What comes to getting around the limitations by casting, I have a feeling that it is in fact UB, but I cannot say for sure. Someone else will surely quote the standard.
This can be done using a C++11 lambda function.
#include <iostream>
#include <sstream>
void f(const char * str)
{
std::cout << str << std::endl;
}
std::string str(void (*populate)(std::ostream &))
{
std::ostringstream stream;
populate(stream);
return stream.str();
}
int main(int argc, char * * args)
{
f(str([](std::ostream & ss){ ss << "Value: " << 5; }).c_str());
return 0;
}
// g++ -std=c++11 main.cpp -o main
// ./main
// Value: 5
If you like one_lined statements you can write:
// void f(const char* str);
f(static_cast<ostringstream*>(&(ostringstream() << "Value: " << 5))->str());
However you should prefer easier to maintain code as:
template <typename V>
string NumberValue(V val)
{
ostringstream ss;
ss << "Value: " << val;
return ss.str();
}
f(NumberValue(5));
I use something a bit like this for logging.
#include <sstream>
using namespace std;
const char *log_text(ostringstream &os, ostream &theSame)
{
static string ret; // Static so it persists after the call
ret = os.str();
os.str(""); // Truncate so I can re-use the stream
return ret.c_str();
}
int main(int argc, char **argv)
{
ostringstream ss;
cout << log_text(ss, ss << "My first message") << endl;
cout << log_text(ss, ss << "Another message") << endl;
}
Output:
My first message
Another message
Since C++17 we have folding expressions for templates that can be used to make generic string formatter that can accept everything that have stream support:
template <class... Args>
std::string format(Args &&... args)
{
std::ostringstream ostr;
(ostr << ... << args);
return ostr.str();
}
The you can use it like: format("Int number: ", 42, " Float number: ", 3.14).c_str().
In C++20 std::format is coming.