Member Avatar for embooglement

I'm trying to write a to string function that would use std::stringstream to convert the the instance data into a string, but haven't been able to get operator overloading to work with it. As soon as I define a new << operator, I get a bunch of ambiguity errors saying that there are multiple overload for the operator that could fit. I'm using a trial version Visual Studio 2010 Proffesional, and had the same problem using Visual C++ 2010 Express.

Here's the code, and the line that's causing the error is "stream << someobject.num;"

#include <sstream>
#include <iostream>

class A 
{ 
public: 
	int num; 
	A(int x) : num(x) {}; 
	friend std::stringstream& operator<<(std::stringstream& stream, const A& someobject);
};

std::stringstream& operator<<(std::stringstream& stream, const A& someobject)
{
	stream << someobject.num;
	return stream;
};

int main(int, char**)
{
	A a1(7);

	std::stringstream stream1;

	stream1 << "Hello world! " << a1;

	std::cout << stream1.str() << std::endl;

	system("pause");

	return 0;
};

Change std::stringstream& to std::ostream& in the overloaded operator and you would be ok.

class A 
{ 
public: 
	int num; 
	A(int x) : num(x) {}; 
	friend std::ostream& operator<<( std::ostream& stream, const A& someobject );
};

std::ostream& operator<<( std::ostream& stream, const A& someobject )
{
	stream << someobject.num;
	return stream;
};

Why is this so? Because in:

std::stringstream stream1;
stream1 << "Hello world! " << a1;

stream1 << "Hello world! " returns a std::ostream&

commented: Perfect solution :) +33
Member Avatar for embooglement

Thank you! This problem has really been bugging me. And that does fix the problem I was getting, but it isn't the exact solution I'd like. Is there any way to only allow insertion into string streams? If not, that's fine, this solution is better than none, and I'll take it.

>>Is there any way to only allow insertion into string streams

If you want to only insert into streams, then use ostringstream. Similarly,
if you want only extraction into the stream, then use istringstream. If you
want both extraction and insertion into the stream then use stringstream.

But if you really want to use stringstream, then you can tell the constructor that it
should only be use to insert into the stream like so :

stringstream stream(std::ios_base::in); //only allow input into the stream.

See here for more details.

Member Avatar for embooglement

firstPerson, I understand how to use string streams like that. What I was asking was if there was a way to overload the << operator so that it only worked with string streams, rather than with all iostreams. For instance, I don't want the user to be able to do "cout << someClass << endl;" But I do want to be able to do "someStringStream << someClass;" However when I overload the << operator in my class, it wouldn't compile. The solution above was to overload the operator to use ostreams, but that would allow it to be used with cout.

> I don't want the user to be able to do "cout << someClass << endl;" But I do want to be able to do "someStringStream << someClass;"

Is that a very good idea? Consider not overloading the stream insertion operator at all, and instead just providing a member function to_string() which can be used to stringify the object.

> However when I overload the << operator in my class, it wouldn't compile.

Modify the (original) overloaded operator to:

std::stringstream& operator<<( std::stringstream& stream, const A& someobject)
{
    static_cast<std::ostream&>(stream) << someobject.num;
    return stream;
}

Why would this compile, while the earlier form (without the cast) wouldn't?
See http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19

Also modify the code in main from

A a1(7);
std::stringstream stream1;
stream1 << "Hello world! " << a1;

To

A a1(7);
std::stringstream stream1;
stream1 << "Hello world! " ;
stream1 << a1;

Why is this change required? See my earlier post.

Member Avatar for embooglement

>Is that a very good idea? Consider not overloading the stream insertion operator at all, and instead just providing a member function to_string() which can be used to stringify the object.

I intended to provide a ToString member function, but I wanted to overload the string stream insertion operator as well, to accommodate a global ToString function. In the grand scheme of things, it is probably a bad design decision. I just wanted to see if I could do it. The reason being that, while insertion into a string stream or standard output ought to result in a string, when used with file streams I might want my classes to behave differently, such as saving binary data instead of string data.

Also, I like the word "stringify." I think I'm going to name the function that instead of ToString.

And thank you for the help and the link, it is very much appreciated.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.