std::ostream & _return = ::operator<<(_os, _event)
Especially I would like to know: What is the data type of _return and How can I print it in console.
std::ostream & _return = ::operator<<(_os, _event);
Especially I would like to know: What is the data type of _return and How can I print it in console.
The code looks for an operator<< at global scope (not in any namespace), which can accept the _os and _event objects as parameters. It's not necessarily true, but given "<<" is the normal way streaming output is done in C++, you can expect that it's probably going to be a function such as:
std::ostream& operator<<(std::ostream&, const Event&);
Where Event is whatever type the _event object has, and I've assumed _os will be some type derived from std::ostream, and consequently able to be handled by a reference to std::ostream.
Almost all such operator<< functions return their first stream argument, so your code is probably doing some output, then effectively assigning to _return as if it were:
std::ostream& _return = _os;
Here, the static type of _return itself is std::ostream& - a reference to a std::ostream (Standard output stream) object, but the run-time type will be whatever type _os has... that's the type of object that operations on _return will invoke polymorphically. This could be ofstream, ostringstream or many other types.
How can I print it in console.
There is no Standard way to get textual type names in C++, though runtime polymorphic types do have runtime type information that includes an optional textual field that's normally populated with a type name of some sort - whether it will have full namespace qualifiers, name mangling or whatever is unspecified, but you can try it easily enough:
std::cout << typeid(_return).name() << '\n';
(For GCC, see Unmangling the result of std::type_info::name for tips on unmangling such type names)
_return is just a variable of type "Reference to std::ostream class object".
And it is initialized with a return value of << operator in global namespace ::operator<<(ostream& os, const some_Obj_reference& ref).
Ttis could be as well
std::ostream & _return = (_os <<_event);
Related
I try to overload operator<< for my class so that it print member when I do
std::cout << obj;
I see that the way to do this is
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// write obj to stream
return os;
}
What are the basic rules and idioms for operator overloading?
However, I try to make my code conforms to Google C++ style guide
https://google.github.io/styleguide/cppguide.html#Reference_Arguments
It says that passing the reference without const is not allowed except for the case that it is needed by convention such as swap(). Is this overloading operator<< in the same category as swap()? or there is a way to do something like
std::ostream& operator<<(std::ostream* os, const T& obj)
^
? or something that does not take non-const reference as the input.
If so, please teach me how to do that. Thank you.
It says that passing the reference without const is not allowed except for the case that it is needed by convention
Well, the stream is conventionally passed as a non-const reference into the stream insertion and extraction operators, so it would appear that the rule has allowed an exception for you. As such, defining the suggested overload should be conforming to the rule despite accepting a non-const reference argument.
That said, I'm not an authority on what Google would consider as convention. If you work for Google, you should know whom to ask; If you don't then you don't need to get stressed over their style.
I would like to use std::stringstream to create formatted strings, but use the class inline so I don't have stringstream local variables flying around. What I mean is this:
#include <iostream>
#include <ostream>
#include <string>
#include <sstream>
int main(int argc, char* argv[])
{
std::string test = ((std::ostringstream&)
(std::ostringstream("") << "This is a test: " << 50.1 << "abc")
).str();
std::cout << test << std::endl;
return 0;
}
This compiles fine in GCC, however the output is the following:
"0x401d0a50.1abc"
So it seems that stringstream treats the first string as a pointer and outputs the address. Subsequent operator<<'s work fine.
How do I fix this?
Thanks!
The reason is that the << operator is a member for void const*, but a free function taking an std::ostream& as the left hand argument for char const*. Your std::ostringstream( "" ) is a temporary: you can call member functions (even non-const member functions) on it, but a temporary cannot be used to initialize the non-const reference of the global function.
EDIT:
Two points: first, as has been pointed out, g++ does do what you
want if you specify -std=c++11. As T.C. points out, this is
specified in §27.7.3.9, which provides a template overload for
all << with an rvalue reference for the std::istream
parameter.
And second, the classic work around is
to start the expression std::ostringstream( "" ).flush() <<.... flush is a member function (and so can be called on
a temporary) which returns an std::ostream& (so everything
else chains nicely); it also does nothing on
a std::ostringstream.
Found it. The C++11 standard special-cases rvalue streams with an extra template operator<< overload. §27.7.3.9 of the standard:
Rvalue stream insertion [ostream.rvalue]
template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);
Effects: os << x
Returns: os
It's obviously a better match than the member operator<< that takes a const void * and hence is selected by overload resolution in C++11 mode. In C++98 mode this overload doesn't exist (since there are no rvalue references) and the only viable overload is the member operator<< (since, as James Kanze explains in his answer, the temporary can't bind to the non-const lvalue reference in the free operator<< overload that takes a const char *).
From cplusplus.com, I saw that ostream class's member function operator<< looks like this:
ostream& operator<< (bool val); ostream& operator<< (int val);
.... and so on.
It does make sense because when you use the Cout object like cout<<x you activate the ostream& operator<< (int val) function, so you actually use the << operator on Cout object. This is very much like every other operator and sends the int variable to the function. What is the difference and what exactly happens when I want to stream an object of my own? Why does the syntax is suddenly ostream& operator<< (**ostream &os**, object ob)?
Why do I need to add the ostream var? I am still using cout<<ob so whay isnt it just ostream& operator<< (object obj)? All I pass is my object. The cout object is allready there.
operator<< is generally defined as a free function; that is, not a member function. Since it is an overloaded binary operator, that means it get's its left argument first and its right argument second.
The operator<< traditionally returns a reference to its left argument to enable the idiomatic chain of output.
To make it obvious to the reader, I tend to define my operator overloads using the lhs and rhs abbreviations; an operator<< would look similar to this, for some type T.
std::ostream& operator<<(std::ostream& lhs, T const& rhs)
{
// TODO: Do something
return lhs;
}
As a member function
As with other binary it could be defined as a member function. That is, let us suppose that you with defining your own iostream. Amongst other things, your class declaration may look like this. Again, T is a particular type.
class MyIOStream : public iostream
{
public:
MyIOStream& operator<<(T const& rhs);
}
In this case operator<< is a member function. It has the same semantics when used as <<.
References
Operators in C and C++ - a great summary of all the operators you can overload and their typical arguments.
why do I need to add the ostream var?
I'm sure it's there so that you can chain outputs together:
cout << foo << bar
The first call, cout << foo will result in an ostream reference that can be used for the << bar part.
Some of the stream extractors are members of basic_istream; because they are members, the basic_istream argument is implied. Some of the stream extractors are not members of basic_istream. Because they are not members, the basic_istream argument has to be part of the declaration.
Like this (oversimplified):
class basic_istream {
public:
basic_istream& operator>>(int& i);
}
basic_istream& operator>>(basic_istream&, std::string& str);
Both can be called in the same way:
int i;
std::cin >> i; // calls basic_istream::operator>>(int&)
std::string str;
std::cin >> str; // calls operator>>(basic_istrea&, std::string&)
From Essential C++: 4.10 Providing Class Instances of the iostream Operators
Often, we wish to both read and write objects of a class. For example,
to display our trian class object, we want to be able to write
cout << train << endl;
To support this, we must provide an overloaded instance of the output
operator:
ostream& operator<< (ostream &os, const Triangular &rhs)
{
os << "(" << rhs.beg_pos() << "," << rhs.length() << ")";
rhs.display(rhs.length(), rhs.beg_pos(), os);
return os;
}
We return the same ostream object passed into the function. This
allows multiple outptu operators to be concatenated. Both objects are
passed by reference. The ostream operand is not declared as const
because each output operation modifies the internal state of the
ostream object.
I'm kind of confused why the ostream operand cannot be declared as const.
If the output operator is declared as the following:
const ostream& operator<< (const ostream &os, const Triangular &rhs)
Is there any problem with the above declaration?
Thanks
The problem is that if the ostream argument (or conversely istream) was a constant reference, then the operator would not be able to modify the stream object. Insertion/extraction to the streams modify the stream state, so the existing operator<< are non-const operations. That in turn means that while you can declare and even define:
std::ostream const & operator<<( std::ostream const & s, Type const & t );
The problem is that the definition would not be able to actually write anything at all into the stream:
std::ostream const & operator<<( std::ostream const & s, Type const & t ) {
s << "Hi"; // Error: operator<<( std::ostream&, const char*) requires a
// non-const `std::ostream&`
return s; // This is fine
}
When outputting the variable rhs, some data members inside ostream& os such as output buffer or position of file write if os is a ofstream must be modified.
Declaring os as const forbids such a modification.
And, as shown here, if os is declared as const, then you cannot use it to output primitive data types since none of ostream::operator<<() is declared as constant member function.
Yes, the ostream argument os is modified by calling <<.
The following code is giving me a compilation error. Can anyone please tell me why?
class mytype {
public:
int value;
mytype(int a) {
value = a;
}
friend ostream& operator<<(ostream& stream, const mytype& a) {
stream << a.value;//works
return stream;
}
friend ostringstream& operator<<(ostringstream& stream, const mytype& a) {
stream << (a.value);//compilation error
return stream;
}
};
Error:
error C2027: use of undefined type
'std::basic_ostringstream<_Elem,_Traits,_Alloc>'
Upon fixing that:
error C2666: 'operator <<' : 18 overloads have similar conversions
Final fix:
Declare constructor as explicit. Works on MSVC then.
I wonder why.
error C2027: use of undefined type 'std::basic_ostringstream<_Elem,_Traits,_Alloc>'
You need #include <sstream> to get the [i/o]stringstream classes.
About the other errors
The problem with an overload of the form
ostringstream& operator<<(ostringstream& stream, const mytype& a)
is that it matches an ostringstream exactly. Why is it a bad thing to have a more exact overload? From the standard, §13.3.3/1-2:
a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2) …
If there is exactly one viable function that is a better function than all other viable functions, then it is the
one selected by overload resolution; otherwise the call is ill-formed
Therefore if operator<<( ostream &, int ) and operator<<( ostringstream &, mytype const & ) are both candidates for stream << value, the former matches int exactly with no conversion but the latter matches ostringstream exactly. Therefore neither can be "not worse" for all arguments, and neither candidate may be chosen.
But the code is valid because of a loophole. Your overload is not a candidate at all, except when you actually use your type in the function call. When you declare/define a friend inside a class block, it does not introduce it to any namespace scope; it merely associates it with the class scope, which allows it to be found if that class type describes one of the arguments being passed.
The standard has this to say about friend declarations, although it's in another section (14.6.5):
Friend declarations do not introduce new names into any scope…
So, MSVC tried to be nice and proactively introduced your friend to its enclosing namespace. Strike against MSVC.
However, when I attempted to add a declaration equivalent to what MSVC did "for free," Comeau and GCC nicely resolved the resulting overloading conflict — strike against them. Or is it? As it turns out, the overloaded call occurs earlier in the file than my recommended declaration. If I move the declaration before class mytype { (which requires forward-declaring mytype), then both properly complain about the ambiguity.
Using an overload before it is declared in namespace scope appears to be well and good according to §3.3-3.4 of the Standard. So actually GCC and Comeau were both in the right. The point of declaration is right after the name of the declared object. (And last I checked, self-referential function declarations can still crash GCC.) ADL invokes unqualified lookup into the enclosing namespace at a point immediately before the enclosing class. (3.4.1/8 final bullet, 3.4.1/9, 3.4.2/2a.) If the friend hasn't been declared before the class, it's legitimately not a candidate. (7.3.1.2/3) Isn't C++ a beautiful language?
How keep the simplified example on GCC, but break subsequent code.
friend ostringstream& operator<<(ostringstream& stream, const mytype& a) {
stream << (a.value);//compilation error
return stream;
}
};
ostringstream& operator<<(ostringstream& stream, const mytype& a); // <- here
Following this declaration, it will be impossible to write an int into an ostringstream.
How to break everything uniformly, with simpler declaration semantics.
class mytype; // <- here
// and here:
inline ostringstream& operator<<(ostringstream& stream, const mytype& a);
class mytype {
public:
Following this declaration, it will be impossible to write an int into an ostringstream… including the friend declarations inside class mytype {}.
Actual solution.
The stream classes are supposed to be indistinguishable. If you really want to determine whether a given stream feeds a string in memory (and you shouldn't), it's best to look at its internal streambuf object, returned by rdbuf(), which actually performs the I/O gruntwork. Even a generic ostream object can have ostringstream functionality if given a stringbuf.
if ( typeid( stream.rdbuf() ) == typeid( stringbuf * ) ) {
// this is effectively a stringstream
} else {
// not a stringstream
}
There is an overload ambiguity in the call to operator<< in the ostringstream overload.
stream << a.value;
There are a number of operator<< overloads that are members of the ostream class, which is a base class of ostringstream. One of these is declared as:
ostream& ostream::operator<<(int);
This overload is an exact match for the right-hand side (a.value is an int) but requires a derived-to-base conversion on the left-hand side (stream is an ostringstream, which is derived from ostream).
However, there is also your ostringstream overload:
ostringstream& operator<<(ostringstream&, const mytype&);
This overload is an exact match for the left-hand side (stream is an ostringstream), and a user-defined converting constructor (your mytype(int) constructor) can be used to convert a.value (an int) to a mytype.
Since one overload matches the first argument better and the other overload matches the second argument better, there is an ambiguity. You can fix this either by:
Explicitly converting the left-hand side to an ostream (using (ostream&)stream = a.value;), or
Remove the user-defined conversion by making the constructor explicit.