The question could be subjective, so the syntax of
std::ostream& operator << (std::ostream & o, const SomeClass &a) {
return o << a.accessor().. ;
}
When do you normally define this for the classes that you write, when do you avoid writing this friend function for your class.
IF I want to stream a class I normally write this:
std::ostream& operator << (std::ostream& o, const SomeClass& a)
{
a.print(o);
return o;
}
Then make print a const method on SomeClass that knows how to serialize the class to a stream.
I would only overload operator<< when that has anything to do with streaming, or with shifting and the class is purely numeral. For writing something into an ostream, as in your code, i think it's fine. Anything else, i think, will cause confusion and i would better use member functions for those other purposes. One other application, which i think i would still do as an exception to the rule, is doing something like this:
StringList list;
list << "foo" << "bar" << "baz";
It is how Qt does it with its string list, and which i find quite nice.
A benefit of Martin's answer above is that you also get polymorphism for free. If you make print(ostream&) a virtual function, then the << operator acts like a virtual function as well!
As to when to overload the operator, do so anytime you think the class should be able to be written to a stream (file, socket, etc...). This might even be only for debug purposes. It is often useful to be able to output the internals of a class, so there is no real downside to overloading this operator.
I would consider using it for something like logging. So you can do:
SystemLog systemLog;
systemLog << "Processing Item #15";
systemLog << "Error 0014: Bad things happened.";
systemLog << system.executeCommand(cmd); // returns a result string
Or maybe for networking as in:
NetworkInterface networkInterface;
string message("Hello World! I'm a server.");
networkInterface << message;
Of course implementing these things as regular function is also possible and might just be preferable. Generally, you should beware of operator overloading. Only use it when it really fits.
I had never ever overloaded this one in production code. Although you might want do this if you log a lot, it'll be useful.
I implement this if, and only if, I intend to make use of that operator. This is pretty much never... my reasons for not implementing it are therefore not using it. If its for public use then include it for completeness, but certainly I wouldn't include this in every class in a project of your own, since for the most part you will not need to output a class to a stream. e.g. If you wrap your entry point in a class, providing this operator will be pointless.
I do it very frequently since it makes dumping the object to a log for debugging really convenient.
Related
I am suppose to reduce it down to [request->headers().getMethodValue())].
I am fairly new to C++. Can someone please tell me how to understand this type of code? There are multiple . operator and -> operator. I loose track of the classes and others.
It's a little overwhelming.
The . operator is used to access stuff inside the object (functions, variables etc.) the -> operator is just a . operator but for pointers. In your case you call request's headers function that returns an object. For that object then you call getMethodValue function.
Actually, those type of codes are common in languages that supports object-oriented programming.
The most likely reason is that if combined well with class hierarchy and inheritance, the single line reduces many if-else statement to terse syntax like one you mentioned. I suggest you study about object-oriented programming styles, especially polymorphism to understand this kind of code.
Answers already explained, what for . operator and -> operator;
an example would be;
class Test
{
public:
print( int i) { std::cout << i << std::endl; }
};
to access pointer object
Test* tPtr;
tPtr->print() // prints i;
to access object;
Test tObj;
tObj.print() // print i;
I just came across this question which is about how to be able to print an object via
std::cout << x << std::endl;
As I understood, the standard way to accomplish this is to overload the ostreams << operator. However, this is adding a feature to the ostream rather than to my class.
The alternative (also given as answer to the above mentioned question) is to override the string conversion operator. However, this comes with the warning of leading to "unintentional conversions and hard-to-trace bugs".
Now i wonder if there are any drawbacks of writing a toString() method and then using it via
std::cout << x.toString() << std::endl;
Output streams handle output formatting as well as output. So with your toString() method clients won't be able to manage the formatting for the object the way they do for everything else:
// set specific formatting options for printing a value
std::cout << std::scientific << std::setprecision(10) << 10.0 << '\n'; // prints 1.0000000000e+01
// set formatting based on user's cultural conventions
std::cout.imbue(std::locale(""));
std::cout << 10000000 << '\n'; // depending on your system configuration may print "10,000,000"
Perhaps you don't care to allow any formatting so perhaps this won't matter.
Another consideration is that outputting to a stream doesn't require that the entire string representation be in memory at once, but your toString() method does.
Others have pointed this out, but I think a clearer way of saying it is that your classes interface is not limited to just the methods it provides, but also includes the other functions you build around it, including non-member functions such as the operator<< overloads you provide. Even though it's not a method of your class you should still think of it as part of your class's interface.
Here's an article that talks about this which perhaps you will find helpful: How Non-Member Functions Improve Encapsulation
Here's a simple example of overloading operator<< for a user defined class:
#include <iostream>
struct MyClass {
int n;
};
std::ostream &operator<< (std::ostream &os, MyClass const &m) {
for (int i = 0; i < m.n; ++i) {
os << i << ' ';
}
return os;
}
int main() {
MyClass c = {1000000};
std::cout << c << '\n';
}
As I understood, the standard way to accomplish this is to overload the ostreams << operator. However, this is adding a feature to the ostream rather than to my class.
And this is good thing. The smaller your class is the better. If popular C++ idiom allows you to have one more thing out of your class why not follow it?
Now i wonder if there are any drawbacks of writing a toString() method
The drawbacks are:
operator<< works in uniform way with builtin types (like int) and user-defined types. toString could be available for classes only
C++ is more heterogeneous than Java. std::string is the most popular string, but still there exist other string classes and they are used.
the string must be created, which potentially might come with a performance hit. If you write to stream directly you avoid it.
They are fundamentally different things. Providing a operator<< overload effectively extends the interface of the stream, making objects of your class type streamable. Providing a toString function extends the interface of your class, making it possible to get a std::string from your class. These represent different things.
The interface of your class should entirely correspond to what it represents in your program logic (single responsibility). Rarely is toString a natural part of a class's interface. However, extending the interface of the stream to accept more objects is much more logical.
That is, in one case you are saying "Now you can stream objects of this class type". In the other case you are saying "You can turn objects of this class type into a std::string." - it just so happens that that std::string is then streamable. Think about it - does it really make sense for my Person class to have a toString function? Since when have I been able to turn people into text?
Your first assumption is wrong. You don't need to make any changes in ostream.
An operator method like operator<< can be defined in two ways: As a method of the ostream class, taking your x object as a parameter, or as a plain old function with two parameters, taking an ostream as the first parameter, and your x object as the second parameter.
There is nothing wrong with a toString() function per class. It has the advantages of being more explicit, it can be made polymorph and it can be used in other situations than streaming, but you need to have a coding rule when working with a team ("was it to_string(), or str(), or streaming()?").
Overloading operator<< is more idiomatic. It just takes ostream as parameter and makes the conversion implicit when streaming, but since this is idiomatic in C++, most will expect an overloaded operator<< when seeing std::cout << x;.
std::string (as most — if not all — standard classes) doesn’t have any virtual methods, so creating an inherited class with virtual methods will result in UB (due most likely to the destructor). (correct me if I am wrong).
I thought that inheriting without polymorphism it’s ok though, until I read upon the net on this subject.
For instance, in this answer: Why should one not derive from c++ std string class? some arguments are given against this practice. The main reason seems to be the slicing problem which will inhibit the added functionality when the derived object is passed to a function in place of a std::string parameter, thus making the non-polymorphism not logical. The idiomatic C++ way is to create free functions if one wants to extend the functionality of string. And I agree with all that, especially since I am an advocate for free functions instead of monolithic classes.
That being said I think that I found a situation that I think actually warrants the non-polymorphic inheritance from std::string. I will first show what issue I am trying to solve, then I will show the reasons why I think inheriting from std::string is the best solution here.
When porting a function used for debugging purposes from C to C++ I realised there is no way to create formatted strings in C++ (not using C-like string functions e.g. sprintf). I.e.:
C version: void someKindOfError(const char *format, ...);
this would be called like:
someKindOfError("invalid argument %d, size = %d", i, size);
C++ version: void someKindOfError(const std::string &message);
to call this to a similar effect would be:
std::stringstream ss;
ss << "invalid argument " << i << ", size = " << size;
someKindOfError(ss.str());
this can’t be a one liner because the << operator returns an ostream. So this requires 2 extra lines and an extra variable.
The solution I came up with is a class called StreamString that inherits from std::string (actually a templated BasicStreamString that inherits from basic_string<>, but that’t not important) and as far as the new functionality goes it has the operator << that mimics the behaviour of the stringstream operator and conversion to and from string.
So the previous example can become:
someKindOfError(StreamString() << "invalid argument " << i << ", size = " << size);
remember that the parameter type is still const std::string &
The class is created and fully functional. And I found this class very useful in a lot of places when a string is need to be created ad-hoc, without the extra burden of having to declare an extra stringstream variable. And this object can be manipulated further like a stringstream, but it is actually a string and can be passed to functions expecting string.
Why I think this is an exception to the C++ idiom:
the object needs to behave exactly like a string when passed to functions expecting a string, so the slicing problem is not an issue.
the only (noteworthy) added functionality is the operator << which I am reluctant to overload as a free function for a standard string object (this would be done in a library).
One alternative I can think of is to create a variadic templated free function. Something like:
template <class... Args>
std::string createString(Args... args);
which allow us to call like this:
someKindOfError(createString("invalid argument ", i , ", size = " , size));
One disadvantage of this alternative is the lost of the ability to easily manipulate the string like an stringstream after it’s creation. But I suppose I can create a free function to handle that too. Also people are use with the operator << to perform formatted inserts.
To round up:
Is my solution bad practice (or worst) or it is an exception to the C++ idiom and it is OK?
If it is bad, what viable alternatives are there? Is createString ok? Can it be improved?
You don't need to derive a class from std::string for this. Just create an unrelated class, say StringBuilder that keeps a std::stringstream internally. Overload operator << for this class and add a std::string cast operator.
Something like this should do the trick (untested):
class StringBuilder
{
std::ostringstream oss;
public:
operator std::string() const
{
return oss.str();
}
template <class T>
friend StringBuilder& operator <<(StringBuilder& sb, const T& t)
{
sb.oss << t;
return *this;
}
};
Your StreamString class is OK, in that there do not seem to be any situations where normal usage of it could get you into trouble. Even so, there are a lot of alternatives that might be more appropriate to this situation.
Use a pre-existing library, such as Boost.Format, rather than rolling your own. This has the advantage of being widely known, tested, supported, etc...
Write someKindOfError to be a variadic template, to match the C version, but with added C++ type-safety goodness. This has the advantage of matching the C version, and so being familiar to your existing users.
Give StringStream a conversion operator or an explicit to_string function, rather than inheriting from std::string. This gives you more flexibility to change the implementation of the StringStream at a later stage. (For example, at a later stage, you might decide that you want to use some kind of cacheing or buffering scheme, but this would be impossible if you do not know exactly when the final string will be extracted from the StringStream).
As it is, your design is conceptually flawed. The only thing that you need is the ability to convert a StringStream to a std::string. Inheritance is an overly heavy-handed way of achieving that goal, when compared to using a conversion operator.
Write your original stringstream code as a one-liner:
someKindOfError(static_cast<std::stringstream &>(
std::stringstream{} << "invalid argument " << i << ", size = " << size).str());
... well, that's pretty ugly, so maybe not. You should consider it though, if your only reason for not doing this was that you thought it was not possible.
I have a class (for logging) which derives from std::ostream. Stripped down, it looks like this:
class bsgs : public std::ostream {
public:
bsgs(const std::string& msg = "") {
// some setup work
}
~bsgs() {
// some cleanup work
}
template<typename T>
bsgs& operator<<(const T& rhs) {
os << rhs;
return *this;
}
private:
std::ostringstream os;
};
I wrote this class to do a few particular things I need like delta compression. Unfortunately, it doesn't work. I need to pass it to a third-party library (with source, but fairly
large and messy) that provides a "set_out" function to direct its output to a std::ostream. The
set_out function prototype is exactly this:
void set_out(std::ostream *out=0, int level=1);
and if I call it as:
set_out(&std::cout, 3);
or
set_out(&std::cerr, 5);
I get exactly the expected behavior. However, if I write:
bsgs logger;
set_out(&logger, 3);
I can see that the logger's constructor and destructor are called as expected but operator<< is never called. I'm not sure why, and I hope this is a simple question. If I can resolve this problem, I'm all set.
Does anyone know what exactly is going on? The problem seems to be that the library has no clue that I'm passing a pointer to a bsgs and not a std::ostream, but fixing the library to accept a wider range of objects than just std::ostream * looks like it might involve touching 500+ lines of code, which I'd like to avoid.
~~~~~~~~~~~~~~
Edit #1: I'm not sure if it is important, but the library has a virtual set_out() = 0; function at the top of its class hierarchy, which is implemented (identically, as far as I can see) in different subclasses. If I were writing the library I would have made set_out a (non-virtual) template function and provided with a specialization for std::ostream, but let users provide whatever they like so long as they define a usable operator<<. Making this change to the library looks like it will be a solid half a day of editing. Maybe there's an easier way?
The library has no clue that you're passing a pointer to a bsgs - you're not overriding a virtual function, there's no polymorphism involved.
You may find that implementing a streambuf and replacing a streams associated stream buffer (ostream::rdbuf) is a more viable solution.
You can always use
std::ostringstream os;
set_out(&os, 3);
When you want to derive from ostream, just create your own implementation of streambuf, which is virtual, and create stream like
std::ostream stream(new myStreamBuf);
set_out(&stream, 3);
Background
I have a container class which uses vector<std::string> internally. I have provided a method AddChar(std::string) to this wrapper class which does a push_back() to the internal vector. In my code, I have to add multiple items to the container some time. For that I have to use
container.AddChar("First");
container.AddChar("Second");
This makes the code larger. So to make it more easier, I plan to overload operator <<. So that I can write
container << "First" << "Second"
and two items will get added to underlying vector.
Here is the code I used for that
class ExtendedVector
{
private:
vector<string> container;
public:
friend ExtendedVector& operator<<(ExtendedVector& cont,const std::string str){
cont.AddChar(str);
return cont;
}
void AddChar(const std::string str)
{
container.push_back(str);
}
string ToString()
{
string output;
vector<string>::iterator it = container.begin();
while(it != container.end())
{
output += *it;
++it;
}
return output;
}
};
It is working as expected.
Questions
Is operator overload written correctly?
Is it a good practice to overload operators in situations like this?
Will there be any performance issues or any other issues with this code?
Any thoughts?
Edit
After hearing the excellent comments, I decided not to overload << as it doesn't make sense here. I removed the operator overload code and here is the final code.
class ExtendedVector
{
private:
vector<string> container;
public:
ExtendedVector& AddChar(const std::string str)
{
container.push_back(str);
return *this;
}
.. other methods
}
This allows me to add
container.AddChar("First").AddChar("Second")
In C#, I can do this more easily by using the params keyword. Code will be like
void AddChar(params string[] str)
{
foreach(string s in str)
// add to the underlying collection
}
I know in C++, we can use ... to specify variable langth of parameters. But AFAIK, it is not type safe. So is it a recommended practice to do so? So that I can write
container.AddChar("First","Second")
Thanks for the replies.
Is operator overload written correctly?
It is, but one can do better. Like someone else mentioned, your function can be defined entirely out of existing, public functions. Why not make it use only those? Right now, it is a friend, which means it belongs to the implementation details. The same is true if you put operator<< as a member into your class. However, make your operator<< a non-member, non-friend function.
class ExtendedVector {
...
};
// note, now it is *entirely decoupled* from any private members!
ExtendedVector& operator<<(ExtendedVector& cont, const std::string& str){
cont.AddChar(str);
return cont;
}
If you change your class, you will not be sure that that your operator<< will still work. But if your operator<< entirely depends only on public functions, then you can be sure that it will work after changes were made to implementation details of your class only. Yay!
Is it a good practice to overload operators in situations like this?
As another guy said again, this is arguable. In many situations, operator overloading will look "neat" at first sight, but will look like hell next year, because you have no clue anymore what you had in mind when giving some symbols special love. In the case of operator<<, i think this is an OK use. Its use as an insertion operator for streams is well known. And i know of Qt and KDE applications that use it extensively in cases like
QStringList items;
items << "item1" << "item2";
A similar case is boost.format which also reuses operator% for passing arguments for placeholders in its string:
format("hello %1%, i'm %2% y'old") % "benny" % 21
It's of course also arguable to use it there. But its use for printf format specifies are well known and so its use is OK there too, imho. But as always, style is also subjective so take it with a grain of salt :)
How can i accept variable length arguments in a typesafe way?
Well, there is the way of accepting a vector if you are looking for homogeneous arguments:
void AddChars(std::vector<std::string> const& v) {
std::vector<std::string>::const_iterator cit =
v.begin();
for(;cit != v.begin(); ++cit) {
AddChar(*cit);
}
}
It's not really confortable to pass it though. You have to construct your vector manually and then pass... I see you already have the right feeling about the vararg style functions. One should not use them for this kind of code and only when interfacing with C code or debugging functions if at all. Another way to handle this case is to apply preprocessor programming. This is an advanced topic and is quite hacky. The idea is to automatically generate overloads up to some upper limit roughly like this:
#define GEN_OVERLOAD(X) \
void AddChars(GEN_ARGS(X, std::string arg)) { \
/* now access arg0 ... arg(X-1) */ \
/* AddChar(arg0); ... AddChar(arg(N-1)); */ \
GEN_PRINT_ARG1(X, AddChar, arg) \
}
/* call macro with 0, 1, ..., 9 as argument
GEN_PRINT(10, GEN_OVERLOAD)
That is pseudo code. You can have a look at the boost preprocessor library here.
Next C++ version will offer far better possibilities. Initializer lists can be used:
void AddChars(initializer_list<std::string> ilist) {
// range based for loop
for(std::string const& s : ilist) {
AddChar(s);
}
}
...
AddChars({"hello", "you", "this is fun"});
It's also possible in next C++ to support arbitrary many (mixed-type) arguments using variadic templates. GCC4.4 will have support for them. GCC 4.3 already partially supports them.
1) Yes, except since AddChar is public there's no reason it needs to be a friend.
2) This is arguable. << is sort of in the position of being the operator whose overloading for "weird" things is at least grudgingly accepted.
3) Nothing obvious. As always, profiling is your friend. You may want to consider passing the string parameters to AddChar and operator<< by const reference (const std::string&) to avoid unnecessary copying.
Is it a good practice to overload
operators in situations like this?
I don't think so. It's confusing as hell for someone who doesn't know that you've overloaded the operator. Just stick to descriptive method names and forget about the extra characters you're typing, its just not worth it. Your maintainer (or you yourself in 6 months) will thank you.
I'd prefer not to overload it that way personally because vectors don't normally have an overloaded left shift operator - it's not really it's idiom ;-)
I'd probably return a reference from AddChar instead like so:
ExtendedVector& AddChar(const std::string& str) {
container.push_back(str);
return *this;
}
so you can then do
container.AddChar("First").AddChar("Second");
which isn't really much bigger than bitshift operators.
(also see Logan's comment about passing strings in by reference instead of by value).
The operator overloading in this case is not good practice as it makes the code less readable. The standard std::vector doesn't have it either for pushing elements, for good reasons.
If you're worried about the caller code being too long, you could consider this instead of the overloaded operator:
container.AddChar("First").AddChar("Second");
This will be possible if you have AddChar() return *this.
It's funny that you have this toString() function. In that case, an operator<< to output to a stream would be the standard thing to use instead! So if you want to use operators make the toString() function an operator<<.
The operator is not correctly overloaded here. There is no reason to make the operator a friend since it can be a member of the class. Friend is for functions which are not actual members of the class (such as when overloading << for ostream so the object can be output to cout or ofstreams).
What you actually want the operator to be:
ExtendedVector& operator<<(const std::string str){
AddChar(str);
return *this;
}
It is usually considered bad practice to overload operators in a way that has them do something than they do normally. << is normally bit shift, so overloading it this way can be confusing. Obviously STL overloads << for "stream insertion" and so along with that it might make sense to overload it for your use in a similar way. But that doesn't seem like what you're doing, so you probably want to avoid it.
There are no performance issues since operator overloading is the same as a regular function call, just the call is hidden because it is done automatically by the compiler.
This is going to make things rather confusing, I would use the same syntax as std::cin into a variable:
std::cin >> someint;
"First" >> container;
This way it is at least an insertion operator. To me when anything has a << overloaded operator I expect it to be outputting something. Just like std::cout.