I have a value-semantic class that I'd like to be "showable" in the same sense as Haskells Show class, or Python provides a universal __str__() function.
In c++:
I could overload operator<<(ostream&, ...) so I can output my class to e.g. cout
I could overload operator std::string() so my class converts to std::string
I could overload operator const char*() so my class converts to const char *.
I could write a str() member, or a to_string(...) free function
Each of these functions could be defined in terms of the other. Is one option better over the others? Are these all the options? What would the most elegant way be to do this given c++11/14/17?
The question is going to be put in hold in a very few minutes, but I will still share my thoughts here.
First, of all, we can remove const char* / std::string() operator overloads from the list. If the class is not a string, it should not be convertible to string, and serialization enablement does not make your class a string.
As for str(), to_string and operator << they a pretty equivalent. However, since for any complex class to_string() and str() are very likely to use ostreams internally, I believe, operator << is the best option.
I don't know whether it's best practice or not but...
for debugging I always define operator<< which gives a summarised output in text form (this means it's easy to stream objects to log files)
for formatted output I would probably choose to implement this in terms of free functions: detail::x_detail_writer write_details(const X&) and then give detail::x_detail_writer (which is a functor) an operator<< overload
for anything but the most trivial object I implement to_string in terms of operator<< if at all.
for aiding with debugging output we have a helper class which goes something like this:
template<class T>
struct make_writeable {
friend std::ostream& operator<<(std::ostream& os, const T& t) {
// example prefix...
os << demangle(typeid(T).name()) << "{";
t.write(os);
// example postfix:
os << " }";
return os;
}
};
then derive some class from this and give it a member function called write:
struct X : make_writeable<X>
{
void write(std::ostream& os) const {
// write out members here. they will appear within the prefix and postfix
}
};
Related
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?
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.
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.
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.
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).
I've got these instructions for an assignment that have put me through a loop here. I need to overload the insertion operator to print out an objects datamembers. However, it states that the overloader has to be a non-friend helper operator.
If that's the case, how can it ever access the private datamembers if its not a 'friend'? And if this is possible, why should I avoid using 'friend'?
Here is what it says word for word:
a helper non-friend operator that inserts the stored string into the left ostream operand.
This operator prefaces the string with the number of the insertion and increment that number
I'm somewhat new to C++ so I really appreciate the help.
If it's not a friend, it needs to use the object's public interface (ergo, you need to write the object's public interface to include the access required by the insertion operator).
For example, you might do something like this:
class thing {
std::string name;
public:
std::string get_name() const { return name; }
// ...
};
std::ostream &operator<<(std::ostream &os, thing const &t) {
return os << t.get_name();
}
Note that I'm definitely not recommending this as good practice--rather the contrary, I think it's often a better idea for the insertion operator to be a friend. But if you're in a class and you're prohibited from doing things the right way, you do what you have to...
I'm trying to create a report/logger Class in c++.
I want to have in the main an object called Report and apply to this class the operator << to write to file multiple strings just like ofstream does.
So instead of using the following code:
ofstream myfile ("d://example.txt");
if (myfile.is_open())
{
myfile << "This is a line.\n" << "Heya!!!" << endl;
myfile.close();
}
I would like to have something like the following :
Report rLogger ("d://example.txt"); // Report C'tor (const string& s)
logger << "This is a line.\n" << "Heya!!!" << endl;
// the destructor of rLogger will close the file when it dies...
I just can't find out a way to write the operator << as a member function which seems exactly what I need here. The only way I can use the operator << is as friend which isn't helpful in this case. Can someone give me an idea how can I implement it as above?
Thank in advance,
Guy
Try the following:
class Report {
public:
Report() {}
Report(std::string _str) : stream(_str) {}
Report& operator <<(std::string str) {
if (stream.is_open())
stream << str;
return *this;
}
~Report() { stream.close(); }
std::ofstream stream;
};
For the above you must also include the <string> header.
It seems you want to create a stream-like type. Do not create a stream like type by overloading the output operator <<! The way to create a new stream-like type is to create a stream buffer (i.e., a type derived from std::streambuf) and use this to initialize an std::ostream object, probably by using std::ostream as a base class.
The other approaches for overloading operator<<() won't work for manipulators like std::endl: the manipulator std::endl is a function template and for deducing it template arguments when being used it is necessary to have an overload which can be used to deduce the type correct. The std::ostream class does this by providing suitable special overloads.
I realize that this isn't answering your question about how to overload operator<<() as a member but I think it is the wrong approach and it will probably yield better results changing the way the problem is addressed. I would provide more detail on how to create the corresponding classes but there isn't sufficient context given.
It seems like your problems stem from needing to insert different types to your report, such as "Heya!!!" or std::endl.
One flexible solution is to do this with templates.
You may implement it as a member function, where the Report is pointed to by this:
class Report {
public:
template < typename T >
Report& operator <<( const T &data ) { ... }
};
Or as a friend function, where there is no this and Report is instead explicitly mentioned and named:
class Report {
public:
template < typename T >
friend Report& operator <<( Report &r, const T &data ) { ... }
};
Or as a stand-alone function, if the Report has enough public methods to do the job.
template < typename T >
Report& operator <<( Report &r, const T &data ) { ... }
To implement it as a member function and be able to concatenate several streams you just have to return a reference to the object at the end of the function, e.g.:
class Report {
public:
// ...
Report& operator<<(const char *text) {
// write text to file...
return *this;
}
};
Here is a very simple example that prints to standard output instead of a file: http://codepad.org/S8QeJZ1x
If all you want is to make sure the file is closed after use, class Report is unnecessary. std::ofstream's destructor already closes its file.
The other answers so far, which try to define a templated operator<< have a problem: They won't work with some manipulators including std::endl, since it's actually a function template, and the compiler can't figure out what sort of instantiation it should use.
If the purpose of class Report is to add or modify something in the data going through, that's more easily and more correctly done by defining your own streambuf. This article by James Kanze describes how to do that.
Following is the abstraction of string class.
class string {
public:
string(int n = 0) : buf(new char[n + 1]) { buf[0] = '\0'; }
string(const char *);
string(const string &);
~string() { delete [] buf; }
char *getBuf() const;
void setBuf(const char *);
string & operator=(const string &);
string operator+(const string &);
string operator+(const char *);
private:
char *buf;
};
string operator+(const char *, const string &);
std::ostream& operator<<(std::ostream&, const string&);
I want to know why these two operator overloaded functions
string operator+(const char *, const string &);
std::ostream& operator<<(std::ostream&, const string&);
are not class member function or friend functions? I know the two parameter operator overloaded functions are generally friend functions (I am not sure, I would appreciate if you could enlighten on this too) however my prof did not declare them as friend too. Following are the definitions of these function.
string operator+(const char* s, const string& rhs) {
string temp(s);
temp = temp + rhs;
return temp;
}
std::ostream& operator<<(std::ostream& out, const string& s) {
return out << s.getBuf();
}
Could anyone explain this with a small example, or direct me to similar question. Thanks in Advance.
Regards
The friend keyword grants access to the protected and private members of a class. It is not used in your example because those functions don't need to use the internals of string; the public interface is sufficient.
friend functions are never members of a class, even when defined inside class {} scope. This is a rather confusing. Sometimes friend is used as a trick to define a non-member function inside the class {} braces. But in your example, there is nothing special going on, just two functions. And the functions happen to be operator overloads.
It is poor style to define some operator+ overloads as members, and one as a non-member. The interface would be improved by making all of them non-members. Different type conversion rules are applied to a left-hand-side argument that becomes this inside the overload function, which can cause confusing bugs. So commutative operators usually should be non-members (friend or not).
Let's talk about operator +. Having it as a non member allows code such as the following
string s1 = "Hi";
string s2 = "There";
string s3;
s3 = s1 + s2;
s3 = s1 + "Hi";
s3 = "Hi" + s1;
The last assignment statement is not possible if operator+ is a member rather than a namespace scope function. But if it is a namespace scope function, the string literal "Hi" is converted into a temporary string object using the converting constructor "string(const char *);" and passed to operator+.
In your case, it was possible to manage without making this function a friend as you have accessors for the private member 'buf'. But usually, if such accessors are not provided for whatever reason, these namespace scope functions need to be declared as friends.
Let's now talk about operator <<.
This is the insertion operator defined for ostream objects. If they have to print objects of a user defined type, then the ostream class definition needs to be modified, which is not recommended.
Therefore, the operator is overloaded in the namespace scope.
In both the cases, there is a well known principle of Argument Dependent Lookup that is the core reason behind the lookup of these namespace scope functions, also called Koenig Lookup.
Another interesting read is the Namespace Interface Principle
Operators can be overloaded by member functions and by standalone (ordinary) functions. Whether the standalone overloading function is a friend or not is completely irrelevant. Friendship property has absolutely no relation to operator overloading.
When you use a standalone function, you might need direct access to "hidden" (private or protected) innards of the class, which is when you declare the function as friend. If you don't need this kind of privileged access (i.e. you can implement the required functionality in terms of public interface of the class), there's no need to declare the function as friend.
That's all there is to it.
Declaring a standalone overloading function as friend became so popular that people often call it "overloading by a friend function". This is really a misleading misnomer, since, as I said above, friendship per se has nothing to do with it.
Also, people sometimes declare overloading function as friend even if they don't need privileged access to the class. They do it because a friend function declaration can incorporate immediate inline definition of the function right inside the class definition. Without friend one'd be forced to do a separate declaration and a separate definition. A compact inline definition might just look "cleaner" in some cases.
I'm a bit rusty with C++ overloads but I would complete the above answers by this simple memo :
If the type of the left-hand operand is a user-defined type (a class, for instance), you should (but you don't have to) implement the operator overloading as a member function. And keep in mind that if these overloads -- which will most likely be like +, +=, ++... -- modify the left-hand operand, they return a reference on the calling type (actually on the modified object). That is why, e.g. in Coplien's canonical form, the operator= overloading is a member function and returns a "UserClassType &" (because actually the function returns *this).
If the type of the left-hand operand is a system type (int, ostream, etc...), you should implement the operator overloading as a standalone function.
By the way, I've always been told that friend keyword is bad, ugly and eats children. I guess it's mainly a matter of coding style, but I would therefore advice you to be careful when you use it, and avoid it when you can.
(I've never been faced to a situation where its use was mandatory yet, so I can't really tell ! )
(And sorry for my bad English I'm a bit rusty with it too)
Scy
Code:
std::ostream& operator<<(std::ostream& os, const BmvMessage& bm);
I don't see anything incorrect, but it gives the following error:
error: `std::ostream& BMV::BmvMessage::operator<<(std::ostream&, const BMV::BmvMessage&)' must take exactly one argument.
I do not know why this happens. Any suggestions are welcome. I have done this before and never came across this error. I have also checked online and it looks like:
ostream& operator<< (ostream& out, char c );`
Take operator<< outside the class, making it a free function. Make it a friend of the class if it needs access to private parts.
The operator has to be a free function, because its first argument is not of the same type as your class. In general, when you overload a binary operator Foo, the member function version only takes a single argument, and FOO(a, b) means a.Foo(b).
Since a << b would invoke a.operator<<(b), but a is the stream, this is of no use for us.
So make a free function, or perhaps a free friend function. Having a public toString member function can help:
class Foo {
public:
std::string toString() const;
// ...
};
std::ostream & operator<<(std::ostream & o, const Foo & x) {
return o << x.toString();
}
You are using the free form signature to define a member function. Member functions have an implicit this argument, so in your case your member function attempt at overloading operator << would result in a function that takes 3 arguments: implicit this, std::ostream& os and BmvMessage const& bm.
You can't define streaming operators as members, since the first argument needs to be of stream class. Instead, you define them as free functions, possibly friended if needed.