29

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?

12
  • Seems like the structures that need a toString() method would be outweighed by those who don't. Just my opinion. Commented Oct 26, 2015 at 23:42
  • What do you want the effect of this 'standard' method to be? In C++ there is no standard way to define a 'conversion to string' (which more often than not is not sensibly possible) and hence no standard way to request such a conversion. Commented Oct 26, 2015 at 23:44
  • 2
    This question: "other than the standard way, is there a standard way?" Commented Oct 26, 2015 at 23:56
  • 11
    operator std::string() const; fight me Commented Oct 27, 2015 at 0:03
  • 1
    Thank you all for all your comment and insight. I am not looking for for what such a method would do (as in what would go into the returned string), but more so, a "common" method name that is agreed upon (hence the standard). If a class writer, decided to provide a method that returned a string representation of the class, at the least there is some sort of agreement on the method name (be it to_string, toString, etc). I figured to_string would be a good choice, since the std already provides such methods for primitive integer types. Commented Oct 27, 2015 at 5:32

5 Answers 5

16

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.

Sign up to request clarification or add additional context in comments.

Comments

5

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

3

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

1

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

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.