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.
Related
According to my knowledge, the name in a nested scope will hide the same name in the enclosing scope, just like what shows below:
namespace ttt {
class A {};
void test(const A&, int)
{
cout << "ttt::test()" << endl;
}
}
void test(const ttt::A&, int)
{
cout << "global::test()" << endl;
}
int main()
{
void test(const ttt::A&, int);
ttt::A a;
test(a, 1);
}
the declaration of void test(const ttt::A&, int); in the main function hides the same name which is in the namespace ttt, so the console prints global::test()(Tested in Visual Studio 2019)
However, when I try the code below:
std::ostream& operator<< (std::ostream& os, const string& str)
{
os << "global::operator" << endl;
return os;
}
int main()
{
std::ostream& operator<< (std::ostream & os, const string & str);
string a = "STD's operator";
cout << a << "STD's operator" << endl;
}
I try to overload the << operator which is a template defined in STL with my own version of <<. According to the first example, the declaration of operator<< in main should hide the STL defined version of <<, then the desired output should be
global::operator
global::operator
global::operator
or a compile error, since I don't know whether endl can be converted to string.
however, the result of the program is:
global::operator
STD's operator
So the second and the last << in the statement cout << a << "STD's operator" << endl; invokes the STL's <<, not the overloaded one define by me. Shouldn't the << already be hidden by the declaration std::ostream& operator<< (std::ostream & os, const string & str); in main ?
Someone may say "STD's operator" is const char*, so that the Argument Dependent Lookup(ADL) adds a better candidate which is std::ostream& operator<< (std::ostream&, const char*) from std namespace. If this is true, then how to explain the first example. The ADL procedure in the first example may add ttt::test(const A&, int) into overloading candidate and that would cause ambiguity in the first example, but that didn't happen, the ttt::test(const A&, int) just been hidden.
Page 798 of "C++ primer 5th" says that "When we pass an object of a class type to a function, the compiler searches the namespace in which the argument’s class is defined in addition to the normal scope lookup". I think my confusion is about the accurate meaning of in addition to.
If it means that the class's namespace has the same precedence of the scope where the function is called, then the first example should cause ambiguity.
If it means that the class's namespace has lower precedence, then all the << in the main function in the second example should be hidden by the version defined by me.
If it means that the class's namespace has higher precedence, then the first example should print "ttt::test()".
So what happened?
ADL is not performed if one of the candidate functions is declared at block scope, like your block scope function declarations. (When ADL is performed, it indeed has no special preferential treatment when picking the most viable candidate)
So your first example, void test(const ttt::A&, int); (which is a block scope declaration for ::test), means that ttt::test is no longer a candidate, and the global ::test is called (removing the block scope declaration makes it ambiguous)
I believe that you are correct here and the second example should call your global operator after constructing a std::string.
Compilers seem to agree that std::cout << a << "STD's operator" << std::endl compiles to the equivalent of std::operator<<(::operator<<(std::cout, a), "STD's operator").operator<<(std::endl). The << std::endl is fine since it's found by member lookup instead of ADL. The problem is that ADL is still used to find std::operator<<(std::ostream&, const char*)
Reading directly from the C++11 standard on what should happen:
"Operators in expressions" [over.match.oper]p2:
If either operand has a type that is a class or an enumeration, a user-defined operator function might be declared that implements this operator [...]. In this case, overload resolution is used to determine which operator function or built-in operator is to be invoked to implement the operator. Therefore, the operator notation is first transformed to the equivalent function-call notation as summarized in Table 11 (where # denotes one of the operators covered in the specified subclasses)
Both operands are of class types, so user-defined operator functions are considered as expected. The relevant subclause of table 11 is 13.5.2, with the expression a#b, which is (a).operator#(b) as a member function and operator#(a, b) as a non-member function.
[over.match.oper]p3
[...] for a binary operator # with a left operand of type cv1 T1 and a right operand of type cv2 T2, three sets of candidate functions, designated member candidates, non-member candidates and built-in candidates, are constructed as follows:
[...]
The set of non-member candidates is the result of the unqualified lookup of operator# in the context of the expression according to the usual lookup in unqualified function calls (3.4.2) except that all member functions are ignored.
Where §3.4.2 is [basic.lookup.arg] "Argument-dependent name lookup".
[basic.lookup.arg]p3 says:
Let X be the lookup set produced by unqualified lookup (3.4.1) and let Y be the lookup set produced by argument dependent lookup (defined as follows). If X contains
a declaration of a class member, or
a block-scope declaration that is not a using-declaration, or
a declaration that is neither a function or a function template
then Y is empty. [...] The set of declarations found by the lookup of the name is the union of X and Y.
Looking only at std::cout << "STD's operator" for simplicity, the name looked up is operator<<. The unqualified lookup finds the block scope declaration for std::ostream& operator<< (std::ostream & os, const string & str); only (and all other declarations are hidden). But since the function declaration in a block scope was found, ADL shouldn't happen and there are no further non-member candidates.
Thus the set of candidate functions is only the global ::operator<<(std::ostream & os, const string &) and the member operator<< in std::ostream and its base classes, of which the global function is the most viable.
Compilers seem to ignore this rule when looking up operators, always performing ADL even if there is a block scope declaration. Writing operator<<(std::cout, "STD's operator") does it correctly and outputs global::operator.
Only in addition to #Artyer's answer.
In practice, you shouldn't ever provide a different definition of std:: functions in a different namespace because the call may accidentally go into a std:: version, with no warning or error.
The robust solution is to name your functions differently or wrap you arguments in a different class object, so that you never accidentally call a std:: function when you don't intend to.
For example, if you want a version of std::isnan that works correctly with -ffast-math, call it isnan2, not isnan which might resolve into std::isnan.
A part of being a good software engineer is preventing potential problems for yourself in the future. And avoiding name clashes with std:: functions which may be found via ADL is robust engineering - a philosophy or way of thinking about engineering that makes accidental semantic changes of existing correctly working code impossible.
In your example, there is no need or justification for creating another version of std::operator<< in another namespace. But there are undesirable problems which arise from from such a decision. In other words, the reward is 0, but the risk is infinite.
This is related to the difference-between-cout-x-and-cout-operator-x question, but still a little different...
#include <iostream>
int main(){
std::cout << "hello" << std::endl;
std::cout.operator<<("hello2");
std::cout.operator<<(std::endl);
operator<<(std::cout, "hello3");
// operator<<(std::cout, std::endl);
return 0;
}
Q1: Why does std::cout.operator<<("hello2"); work?
From other answers on SO I would expect the compiler to complain since operator<< is meant to be a free function and not a member of cout. On my system, however, it prints "0x10d54df31". And, stranger yet, the following line correctly correctly executes std::endl.
Q2: Why does operator<<(std::cout, std::endl); not work?
I know that std::endl is a function, but it seems strange (to me) that the hello3 output works whilst the `std::endl' doesn't. Instead the compiler throws an error:
main.cpp:10:4: error: no matching function for call to 'operator<<'
operator<<(std::cout, std::endl);
Q3: How can the first std::cout << "hello1" << std::endl; be written in operator<<(...) form?
If the first two questions have been answered, then this has probably already covered. It's the point of this learning exercise, so seems sensible to ask it explicitly.
Operators can be implemented in different ways, in particular an operator<< for which the left hand side is your type can be implemented as either a free function or as a member function of that left hand side type.
While you must implement ostream& operator<<(ostream&, MyType const&) as a free function (since MyType is not the left hand side), the library implementation can choose* to implement operator<< for some fundamental types insde the std::ostream type (which is really a particular instantiation of a template, I am trying to ignore the details).
Edit: After checking with the standard this is incorrect:
This is what you are noticing in the code, the overload that takes a const char* is implemented as a member of ostream (basic_ostream<char,char_traits<char>).
The overloads taking manipulators are implemented as member functions (Q2), and there is an implicit conversion from const char* to const void* that will be picked if you use the syntax for explicitly calling a member operator (Q1). For Q3, the answer would be:
operator<<(std::cout, "Hello").operator<<(std::endl);
* The implementation is actually not free to choose, since the standard mandates the signatures.
Some overloads of operator<< are class members, others are not.
In C++03 this created some baffling call scenarios since a reference to non-const (argument of the not-member) can't be bound to an rvalue, but in C++11 at least one such has been fixed by introducing an rvalue reference argument overload.
So, which calls compile or not depends more in general also on the C++ standards version, C++03 or C++11.
There is a bunch of member output operators defined in std::ostream. In retrospect that was probably an error but when IOStreams were first created I think it was actually necessary. These member operators include the overloads taking function pointers which means you'll need to use member notation for those. The operators using C-strings are non-member overloads, i.e., you need to use the non-member function call notation to get the C-string overload. When you call the member operator with a char const* the char const* will be converted to void const* for which there is a member output operator.
Your questions can be broken down to member functions an non-member functions.
Having 13.5.2 Binary operators
A binary operator shall be implemented
either by a non-static member function (9.3) with one parameter or by
a non-member function with two parameters. Thus, for any binary
operator #, x#y can be interpreted as either x.operator#(y) or
operator#(x,y). If both forms of the operator function have been
declared, the rules in 13.3.1.2 determine which, if any,
interpretation is used.
Omitting a quote of 13.3.1.2 the member function (operator) is preferred.
The line 'std::cout << "hello" << std::endl;' involves non member functions. Each 'std::cout.operator' is an explicit member function call.
Q1 is the member operator<<(const void*)
Q2 there is no member taking a function
Q3 It is not possible
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&)
Why it is not allowed to overload "=" using friend function?
I have written a small program but it is giving error.
class comp
{
int real;
int imaginary;
public:
comp(){real=0; imaginary=0;}
void show(){cout << "Real="<<real<<" Imaginary="<<imaginary<<endl;}
void set(int i,int j){real=i;imaginary=j;}
friend comp operator=(comp &op1,const comp &op2);
};
comp operator=(comp &op1,const comp &op2)
{
op1.imaginary=op2.imaginary;
op1.real=op2.real;
return op1;
}
int main()
{
comp a,b;
a.set(10,20);
b=a;
b.show();
return 0;
}
The compilation gives the following error :-
[root#dogmatix stackoverflow]# g++ prog4.cpp
prog4.cpp:11: error: ‘comp operator=(comp&, const comp&)’ must be a nonstatic member function
prog4.cpp:14: error: ‘comp operator=(comp&, const comp&)’ must be a nonstatic member function
prog4.cpp: In function ‘int main()’:
prog4.cpp:25: error: ambiguous overload for ‘operator=’ in ‘b = a’
prog4.cpp:4: note: candidates are: comp& comp::operator=(const comp&)
prog4.cpp:14: note: comp operator=(comp&, const comp&)
Because if you do not declare it as a class member compiler will make one up for you and it will introduce ambiguity.
The assignment operator is explicitly required to be a class member operator. That is a sufficient reason for the compiler to fail to compile your code. Assignment is one of the special member functions defined in the standard (like the copy constructor) that will be generated by the compiler if you do not provide your own.
Unlike other operations that can be understood as external to the left hand side operator, the assignment is an operation that is semantically bound to the left hand side: modify this instance to be equal to the right hand side instance (by some definition of equal), so it makes sense to have it as an operation of the class and not an external operation. On the other hand, other operators as addition are not bound to a particular instance: is a+b an operation of a or b or none of them? -- a and b are used in the operation, but the operation acts on the result value that is returned.
That approach is actually recommended and used: define operator+= (that applies to the instance) as a member function, and then implement operator+ as a free function that operates on the result:
struct example {
example& operator+=( const example& rhs );
};
example operator+( const example& lhs, const example& rhs ) {
example ret( lhs );
ret += rhs;
return ret;
}
// usually implemented as:
// example operator+( example lhs, const example& rhs ) {
// return lhs += rhs; // note that lhs is actually a copy, not the real lhs
//}
Assignment(=) operator is a special operator that will be provided by the constructor to the class when programmer has not provided(overloaded) as member of the class.(like copy constructor).
When programmer is overloading = operator using friend function, two = operations will exists:
1) compiler is providing = operator
2) programmer is providing(overloading) = operator by friend function.
Then simply ambiguity will be created and compiler will gives error. Its compilation error.
There is no good reason for that, I think Stepanov proposed that there should be a free operator= and many good stuff can be done with that (even more than what can be done with the move assignment). I can't find the citation but Stepanov went as a far as to suggest that the constructors could be free functions http://www.stlport.org/resources/StepanovUSA.html.
There is a way around it, which is to systematically declare a template<class Other> A& operator=(Other const& t); in inside all your classes, in this way you leave the option to anyone to define a custom assignment operator.
Of course you can't do this with a class you don't have control over.
Having said that it is nowadays not that bad since we have move assignment. And in some sense conversion operators B::operator A() const{...} are almost like a custom copy assignment. Conversion operators are now usable because of explicit. However you have to have control over the second type (B), the right-hand type in assignment.
Next question is why conversion operator need to be members them selves? Again, I don't think there is a good reason.
Hi I have a code like this, I think both the friend overloaded operator and conversion operator have the similar function. However, why does the friend overloaded operator is called in this case? What's the rules?
Thanks so much!
class A{
double i;
public:
A(int i):i(i) {}
operator double () const { cout<<"conversion operator"<<endl;return i;} // a conversion operator
friend bool operator>(int i, A a); // a friend funcion of operator >
};
bool operator>(int i, A a ){
cout<<"Friend"<<endl;
return i>a.i;
}
int main()
{
A aa(1);
if (0 > aa){
return 1;
}
}
No conversion is necessary for the overloaded operator> to be called. In order for the built-in operator> to be called, one conversion is necessary (the user-defined conversion operator. Overload resolution prefers options with fewer required conversions, so the overloaded operator> is used.
Note that if you were to change the definition of your overloaded operator> to be, for example:
friend bool operator>(double i, A a);
you would get a compilation error because both the overloaded operator> and the built-in operator> would require one conversion, and the compiler would not be able to resolve the ambiguity.
I am not claiming that my answer is supported by the standards, but lets think about it logically.
When you hit this line:
0 > aa
You have two options. Either you call the provided operator:
friend bool operator>(int i, A a);
Which is 100% compatible, or you can do two conversions to reach your destination! Which one would you choose?
If you add a conversion operator then an object of type A may be converted to double when you least expect it.
A good program does not provide a way for his classes to be accidently used and the conversion operator opens up the opertunity for the class to be used in a whole host of unintended situations (normally situations where you would expect a compile time error are not because of the auto type conversion).
As a result conversion operators (and single argument constructors) should be treateed with some care because of situations were the compiler may do conversion when you least expect it.
It is called because it is an exact match in the context of the expression 0 > aa. In fact, it is hard to figure out how you came up with the "why" question. By logic, one'd expect a "why" question if the friend weren't called in this case.
If you change the expression to 0.0 > aa, the call will beciome ambiguous, because neuther path will be better than the other.