In Java, the standard is to define the method toString() to return a string representation of a class. Other than overloading operator<<, is there any such standard in C++? I know there are the std::to_string() methods to get a string representation of a number. Does the C++ standard speak of defining the method to_string() to serve similar purpose for a class, or is there a common practice followed by C++ programmers?
5 Answers
The standard way to do this kind of thing is to provide an insertion operator so that an object can be inserted into a stream -- which may be any kind of stream, such as a stringstream.
If you wish, you can also provide a method that converts to a string (useful for your insertion operator), and, if you find the conversion acceptable, you can provide a 'to string' operator.
Here's my standard 'point' class example:
template <typename T>
struct point
{
T x;
T y;
point(): x(), y() { }
point( T x, T y ): x(x), y(y) { }
};
template <typename T>
std::ostream& operator << ( std::ostream& outs, const point <T> & p )
{
return outs << "(" << p.x << "," << p.y << ")";
}
I also tend to keep a handy function around to convert things to strings:
template <typename T>
std::string to_string( const T& value )
{
std::ostringstream ss;
ss << value;
return ss.str();
}
Now I can use it easily:
int main()
{
point p (2,-7);
std::cout << "I have a point at " << p << ".\n";
my_fn_which_takes_a_string( to_string(p) );
You'll find that the Boost Lexical Cast Library is also designed for this kind of thing.
Hope this helps.
Comments
The C++ standard does not prescribe a way to do this but it looks like there is a proposal which may introduce such an option Generic to_string/to_wstring functions which says in the motivation section which also highlights the current common practices being taken(which I demonstrate below):
For a long time C++ programmers have been looking for an easy way to convert an object into its string representation. A typical answer to this problem was to create a local ostringstream, insert the object into the stream, and then obtain the resulting string with the str member function. This solution is simple, safe, flexible and extensible, though definitely too verbose for something that rather ought to be a single function call. C++11 provided (a partial) solution in the form of a set of overloaded to_string/to_wstring functions. Unfortunately, these are limited only to the built-in numeric types. Non-standard solutions exist too – most notably boost::lexical_cast, which offers two-way conversion of objects and strings, but lacks any formatting control.
This paper proposes a solution that:
- generalizes the existing to_string/to_wstring functions for any type that provides a stream output operator and for any basic_string specialisation,
- remains consistent and mostly compatible with these functions,
- provides extra formatting and concatenation capabilities,
- is conceptually simple by building upon the familiar ostringstream solution.
There are two trip reports STL's and Herb Sutter's and I don't see this paper mentioned in either. So hopefully this will be covered in the post-Kona mailing when it comes out.
The first method they mentioned in the proposal would look something like the example in this answer:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
combined with the something similar to the example from here:
template <typename T>
std::string to_string(const T& value) {
std::ostringstream os;
os << value;
return os.str();
}
We can find a boost::lexical_cast example in the question Enabling Classes for Use with boost::lexical_cast.
Comments
Looks like there is no standard way. As I understand C++ standard does not permit overloading of std::to_string function.
I ended up using one of these two solutions:
Solution #1
Instead of toString() method you can use:
operator std::string() const {
return "Object string.";
}
And to support streams you can add something like this:
friend std::ostream & operator <<(std::ostream &out, const YourClass &obj) {
return out << static_cast<std::string>(obj);
}
I hope that the << operator will just inline the conversion from the first operator.
Solution #2
Or you can go other way if you think often in the stream-style:
friend std::ostream & operator <<(std::ostream &out, const YourClass &obj) {
out << "Object ";
out << "string.";
return out;
}
And use it inside conversion operator:
operator std::string() const {
std::ostringstream out;
out << *this;
return out.str();
}
Either way this get you covered for most of the cases.
Comments
Does the C++ standard speak of defining the method to_string() to serve similar purpose for a class,
No.
or is there a common practice followed by C++ programmers.
No. However, I suspect every project has similar functionality. The name and return type most likely depend on the coding guidelines of a project.
At my work, we use
virtual QString toString() const = 0;
in one of our base classes.
You can start using something similar for your project.
virtual std::string toString() const = 0;
in your base class(es).
Comments
In c++20 you can use std::format and specify custom formatter for structs and classes. An example taken from here:
#include <format>
#include <iostream>
#include <string>
struct Point {
int x{2017};
int y{2020};
int z{2023};
};
template <>
struct std::formatter<Point> : std::formatter<std::string> {
auto format(Point point, format_context& context) const {
return formatter<string>::format(
std::format("({}, {}, {})",
point.x, point.y, point.y), context);
}
};
int main() {
Point point;
std::cout << std::format("{}", point) << '\n';
}
Note that your compiler's libstd++ implementation might not support std::format yet.
toString()method would be outweighed by those who don't. Just my opinion.operator std::string() const;fight me