operator << must take exactly one argument - c++

a.h
#include "logic.h"
...
class A
{
friend ostream& operator<<(ostream&, A&);
...
};
logic.cpp
#include "a.h"
...
ostream& logic::operator<<(ostream& os, A& a)
{
...
}
...
When i compile, it says:
std::ostream& logic::operator<<(std::ostream&, A&)' must take exactly one argument.
What is the problem?

The problem is that you define it inside the class, which
a) means the second argument is implicit (this) and
b) it will not do what you want it do, namely extend std::ostream.
You have to define it as a free function:
class A { /* ... */ };
std::ostream& operator<<(std::ostream&, const A& a);

A friend function is not a member function, so the problem is that you declare operator<< as a friend of A:
friend ostream& operator<<(ostream&, A&);
then try to define it as a member function of the class logic
ostream& logic::operator<<(ostream& os, A& a)
^^^^^^^
Are you confused about whether logic is a class or a namespace?
The error is because you've tried to define a member operator<< taking two arguments, which means it takes three arguments including the implicit this parameter. The operator can only take two arguments, so that when you write a << b the two arguments are a and b.
You want to define ostream& operator<<(ostream&, const A&) as a non-member function, definitely not as a member of logic since it has nothing to do with that class!
std::ostream& operator<<(std::ostream& os, const A& a)
{
return os << a.number;
}

I ran into this problem with templated classes.
Here's a more general solution I had to use:
template class <T>
class myClass
{
int myField;
// Helper function accessing my fields
void toString(std::ostream&) const;
// Friend means operator<< can use private variables
// It needs to be declared as a template, but T is taken
template <class U>
friend std::ostream& operator<<(std::ostream&, const myClass<U> &);
}
// Operator is a non-member and global, so it's not myClass<U>::operator<<()
// Because of how C++ implements templates the function must be
// fully declared in the header for the linker to resolve it :(
template <class U>
std::ostream& operator<<(std::ostream& os, const myClass<U> & obj)
{
obj.toString(os);
return os;
}
Now:
* My toString() function can't be inline if it is going to be tucked away in cpp.
* You're stuck with some code in the header, I couldn't get rid of it.
* The operator will call the toString() method, it's not inlined.
The body of operator<< can be declared in the friend clause or outside the class. Both options are ugly. :(
Maybe I'm misunderstanding or missing something, but just forward-declaring the operator template doesn't link in gcc.
This works too:
template class <T>
class myClass
{
int myField;
// Helper function accessing my fields
void toString(std::ostream&) const;
// For some reason this requires using T, and not U as above
friend std::ostream& operator<<(std::ostream&, const myClass<T> &)
{
obj.toString(os);
return os;
}
}
I think you can also avoid the templating issues forcing declarations in headers, if you use a parent class that is not templated to implement operator<<, and use a virtual toString() method.

Operator overloading includes member function overloading and non-member function overloading, which cannot be mixed. https://condor.depaul.edu/ntomuro/courses/262/notes/lecture3.html

If you define operator<< as a member function it will have a different decomposed syntax than if you used a non-member operator<<. A non-member operator<< is a binary operator, where a member operator<< is a unary operator.
// Declarations
struct MyObj;
std::ostream& operator<<(std::ostream& os, const MyObj& myObj);
struct MyObj
{
// This is a member unary-operator, hence one argument
MyObj& operator<<(std::ostream& os) { os << *this; return *this; }
int value = 8;
};
// This is a non-member binary-operator, 2 arguments
std::ostream& operator<<(std::ostream& os, const MyObj& myObj)
{
return os << myObj.value;
}
So.... how do you really call them? Operators are odd in some ways, I'll challenge you to write the operator<<(...) syntax in your head to make things make sense.
MyObj mo;
// Calling the unary operator
mo << std::cout;
// which decomposes to...
mo.operator<<(std::cout);
Or you could attempt to call the non-member binary operator:
MyObj mo;
// Calling the binary operator
std::cout << mo;
// which decomposes to...
operator<<(std::cout, mo);
You have no obligation to make these operators behave intuitively when you make them into member functions, you could define operator<<(int) to left shift some member variable if you wanted to, understand that people may be a bit caught off guard, no matter how many comments you may write.
Almost lastly, there may be times where both decompositions for an operator call are valid, you may get into trouble here and we'll defer that conversation.
Lastly, note how odd it might be to write a unary member operator that is supposed to look like a binary operator (as you can make member operators virtual..... also attempting to not devolve and run down this path....)
struct MyObj
{
// Note that we now return the ostream
std::ostream& operator<<(std::ostream& os) { os << *this; return os; }
int value = 8;
};
This syntax will irritate many coders now....
MyObj mo;
mo << std::cout << "Words words words";
// this decomposes to...
mo.operator<<(std::cout) << "Words words words";
// ... or even further ...
operator<<(mo.operator<<(std::cout), "Words words words");
Note how the cout is the second argument in the chain here.... odd right?

The key point is the logic:: before operator<< which is defined as a friend function.
logic:: is only added before the member function. I understand that this is similar to telling the compiler that this function is a member function and granting it corresponding permissions (such as accessing private functions).
In other words, just as #asaelr and #Morteza mentioned, "when defining a friend function you do not use the name of the class to scope the name of the friend function".
Hence, we should remove logic:: before operator<<.

Related

operator<< overload as a member function, why does it not work? [duplicate]

I am trying to overload operator<< as a member function. It works if simply do this:
friend ostream& operator<<(ostream& os, const MyClass& myClass); in my header file and in my MyClass.cc file:
ostream& operator<<(ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
However, if I try to take the friend off and make it a member function, then it complains that operator<< can only take one argument. Why?
ostream& MyClass::operator<<(ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
I read at this question that it can't be a member function, but not sure why?
When overloaded as a member function, a << b is interpreted as a.operator<<(b), so it only takes one explicit parameter (with this as a hidden parameter).
Since this requires that the overload be part of the class used as the left-hand operand, it's not useful with normal ostreams and such. It would require that your overload be part of the ostream class, not part of your class. Since you're not allowed to modify ostream, you can't do that. That leaves only the global overload as an alternative.
There is, however, a fairly widely-used pattern where you overload the operator globally, but have that call a member function:
class whatever {
// make this public, or the global overload a friend.
std::ostream &write(std::ostream &dest) const {
// write self to dest
}
};
std::ostream &operator<<(std::ostream &os, whatever const &w) {
return w.write(os);
}
This is particularly useful when/if you want polymorphic behavior. You can't make the overloaded operator polymorphic itself, but you make the member function it calls virtual, so it acts polymorphic anyway.
Edit: to (I hope) clarify the situation, you can do this a few different ways. The first and probably most obvious is to just make our write member public, and have the global operator call it. Since it is public, we don't have to do anything special to let the operator use it:
class myClass {
public:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
};
std::ostream &operator<<(std::ostream &os, myClas const &m) {
// since `write` is public, we can call it without any problem.
return m.write(os);
}
A second alternative is to make write private, and declare operator<< a friend to give it access:
class myClass {
// Note this is private:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
// since `write` is private, we declare `operator<<` a friend to give it access:
friend std::ostream &operator<<(std::ostream &, myClass const &);
};
std::ostream &operator<<(std::ostream &os, myClas const &m) {
return m.write(os);
}
There's a third possibility that's almost like the second:
class myClass {
// Note this is private:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
// since `write` is private, we declare `operator<<` a friend to give it access.
// We also implement it right here inside the class definition though:
friend std::ostream &operator<<(std::ostream &os, myClas const &m) {
return m.write(os);
}
};
This third case uses a rather strange (and little known) rule in C++ called "name injection". The compiler knows that a friend function can't be part of the class, so instead of defining a member function, this "injects" the name of that function into the surrounding scope (the global scope, in this case). Even though operator<< is defined inside the class definition, it's not a member function at all -- it's a global function.
You can overload operator<< as a member function. But you can't write a member operator<< that takes an ostream on the left side, and your class on the right side.
When you make something a (non-static) member function, there is an implied first argument, the calling object. operator<< is binary, so it only takes 2 arguments. If you make it a member function, you can only give it one paremeter, because it already has one(the calling object). And since that calling object is always the first argument, you can't possibly write the output operator as a (non-static) member (at least, not in the standard form for that particular function), because for that case, the ostream needs to be the first argument.
Think of it like this: when you want to stream to ostream, you're calling the << operator on the stream object. And you're not allowed to directly modify the ostream's 'private' method. So you have to create an overloaded version, and make it a friend.
When you create your own operator<< method in your class, you're creating a << method that will operate on your class, not an ostream object. I guess you can hold an ostream internally to your class and stream to it, but you'll have difficulty writing chained statements like this: a << b << c.

Overloading the stream insertion (<<) operator for a class

It is often overloaded as a friend function of the class. Is there any way it can be overloaded as a member function?
Is there any way it can be overloaded as a member function?
Let's say if you have a class Foo and you want to use:
Foo foo;
std::cout << foo;
No, it cannot.
A member function overload works only if the first argument is an object of the class. In the case of stream insertion operators, the first argument is a stream, not an object of the class.
If you want to use:
Foo foo;
foo << std::cout;
Yes, it can be defined as a member function.
A non-member function and a virtual member function can be combined to good effect when used in a situation where derived classes are involved.
struct Shape
{
// Member function that can be overridden by derived classes.
virtual std::ostream& operator<<(std::ostream& os) const = 0;
};
// Non-member function that makes use of member functions.
std::ostream& operator<<(std::ostream& os, Shape const& shape)
{
return shape << os;
}
struct Rectangle : public Shape
{
virtual std::ostream& operator<<(std::ostream& os) const
{
// Do the need full to stream a Rectangle.
// ...
return os;
}
};
struct Ellipse : public Shape
{
virtual std::ostream& operator<<(std::ostream& os) const
{
// Do the need full to stream an Ellipse.
// ...
return os;
}
};
Usage:
Rectangle r;
Ellipse e;
std::cout << r << std::endl;
std::cout << e << std::endl;
If you wanted to badly enough, you could use a member function overload, but it's directly contrary to convention, so doing it would lead to confusion. It would also prevent chaining extraction/insertion operators, and wouldn't work for reading/writing primitive types.
The reason behind this is that invoking an operator overloaded as a member function means that x << y; is interpreted as x.operator<<(y);, so the overloaded operator has to be a member of the left operand, not the right. It's possible to do that (iostreams include such overloads for some types), but it's essentially impossible to extend (all such overloads have to be part of the iostream object when it's the left operand).
If you want to overload it as a member of the object to be read/written, you need to put the object being read/written as the left operand. This means insertion would go from left to right instead of right to left. To have at least some chance of maintaining sanity, you'd almost certainly want to use >> for insertion, and << for extraction:
class my_class {
int x;
public:
bool operator<<(std::istream &is) {
// Note the reversal here. That's because we're defining this
// for a `my_class` on the left, and an iostream on the right,
// but the existing `>>` and `<<` use the reverse of that (iostream
// on the left).
is >> x;
return is.good();
}
bool operator>>(std::ostream &os) {
os << x;
return os.good();
}
};
my_class a;
a >> std::cout;
a << std::cin;
Note: I'm providing this answer only to point out that it's technically possible to do this, and show how. If you were starting over with a clean slate and you were really set on using member functions, I can see where you might conceivably choose this method--but even then, it's open to a lot of question.
In particular (as noted above) this would not support chaining. Since the insertion and extraction are done as member functions of the left operand, it also means it would only work for user-defined types, not any primitive types (int, short, long, float, double, bool, etc.)
Bottom line: if you want to badly enough, you can get it to work to a limited degree under limited circumstances--but neither well (no chaining) nor universally (no primitive types).
Is there any way it can be overloaded as a member function?
No. The signature of the function prevents this option.
// Binary operator where the stream object is left of '<<' and the object
// instance is right of '<<'
std::ostream& operator<<(std::ostream& lhs, const Foo& rhs)
For illustration here's a binary operator+ as a free function:
class Foo
{
};
Foo operator+(const Foo& lhs, const Foo& rhs)
{
// an appropriate implementation
}
int main()
{
Foo f1;
Foo f2;
// Uses the free function
Foo result = f1 + f2;
return 0;
}
However implemented as a member function it looks like this:
class Foo
{
public:
Foo operator+(const Foo& other) const
{
// an appropriate implementation
}
};
int main()
{
Foo f1;
Foo f2;
// The calling sequence is the same as before however 'f1' is logically
// the same as 'lhs' in the free function implementation example (i.e.,
// the first type in the binary operator must be the class type when
// implemented as a member function)
Foo result = f1 + f2;
return 0;
}
Given the operator+ member function example it is easier to see why the std::ostream& operator<<(std::ostream& lhs, const Foo& rhs) free function cannot be converted to an equivalent member function. Because 'lhs' would need to be the same type as std::ostream but this is only possible when implementing that class whereas in this example the Foo class is being implemented.

Can I unambiguously define both a stream operator and a conversion operator?

I'm trying to create a class which has both overloaded operator<< and operator>> friend functions, and an operator std::string method, something like this:
class MyClass
{
public:
operator std::string()
friend std::istream& operator>>(std::istream&, const MyClass&);
friend std::ostream& operator<<(std::ostream&, const MyClass&);
};
What I find is that my compiler complains about "ambiguous overload" of the stream operators when I try to use them. I think it's because if I write this:
myStream << MyClass();
The compiler doesn't know whether to use the operator<< for MyClass, or to use the operator std::string for MyClass first, and then use the operator<< for std::string (defined in the standard library) to write into the stream.
Is this actually the cause? If so, is there any way to get around it? I know in C++11 you can use the explicit keyword on conversion operators to prevent implicit conversions, but the project I'm working on is currently compiled as C++03.
First, keyword explicit has existed since the 1998 standard. Are you sure your compiler does not support it?
Moreover, I was skeptical about your explanation because the expression std::cout << MyClass() is a perfect match for your overload of operators << and >>, assuming your 'myStream' is of the corresponding stream type. A perfect match takes precedence over any match that requires user defined conversions. Indeed, the following code compiled just fine for me. Which compiler are you using?
class MyClass {
public:
operator std::string();
friend std::istream& operator>>(std::istream&, const MyClass&);
friend std::ostream& operator<<(std::ostream&, const MyClass&);
};
void just_do_it()
{
std::cout << MyClass();
}

Relation between ostream insertion operator and its non-member overload

int i=0;
std::cout << i;
1, The non-member overload(two arguments, one being ostream& the other being type of operand, say int) is defined in std namespace. So if using namespace std; is not present, there's no way I see that the non-member overload can be called.
2, If instead, the member operator(member of ostream; one argument, being the type of operand, say int) function << of ostream is called, I'd expect something like: std::cout.operator<< i; --- isn't this rediculous?
So, what on earth is the relation between the two?
Question extended: if I want to overload the insertion operator so that std::cout << my_obj; works(assume my_obj is the instance of a user-defined type, MyType), should I do
a) ostream& operator<< (ostream& os, MyType obj); in the namespace of MyType
or
b) in MyType:
class MyType
{
...
ostream& operator<< (MyType);
};
does option b) ever work? Does it even make sense(I remember seeing it somewhere ...)? What's the relation between option a) & b)?
EDIT MAR 27
Upon the request from ecatmur, here're two overloads that have the same signature but in different namespaces. Using gcc 4.9.2: http://melpon.org/wandbox/
#include <iostream>
namespace MyNameSpace
{
class MyType
{};
// signature can be found here: http://www.cplusplus.com/reference/ostream/ostream/operator-free/
std::ostream& operator<<(std::ostream& out, char ch)
{
out << "std is doomed\n";
return out;
}
std::ostream& operator<<(std::ostream& out, MyType t)
{
out << "std is super doomed\n";
return out;
}
}
int main()
{
MyNameSpace::MyType t;
std::cout << t; // ... super doomed; ADL is working as intended.
std::cout << 't'; // t; this proves that when there're two operator overloads with the same signature but in different namespaces, there're no compilation errors. gcc defaults to the std one.
return 0;
}
The non-member overloads you're thinking of are those for character data and those for std::string etc.; they're available via argument-dependent lookup. You can indeed write std::cout.operator<<(i) for types where ostream has a member operator<<.
For your own types you're thinking of a (non-member) friend operator<<, which can be particularly useful for template classes (the Barton-Nackman trick) or for those where the operator<< accesses data not available via accessors:
class MyType
{
...
friend std::ostream& operator<< (std::ostream&, MyType obj) { ... }
};
Your proposed signature would allow you to write my_obj << my_obj, which is unlikely to make much sense.

How do you pass overload operator members of classes as function pointers?

For example, if I wanted to pass
ostream& std::ostream::operator << (int i);
into a function such as
void func(ostream& (*out)(int), ...);
then how would I go about doing that?
Doing
func(std::ostream::operator << (int))
surely does not work and
typedef ostream& (*out)(int);
out o = std::ostream::operator << (int);
func(o);
throws a compile-time error when trying to assign o. So how does one point to overloaded operators? (casting to type out does not work in this situation either)
After playing around with the code, my question is now this: why is it that non-member, overloaded operators i.e
ostream& operator << (ostream&, classX)
return a void* and not a pointer to a function?
If I do
typedef ostream& (*out)(ostream&,classX);
I can only make it
void* v = ostream& operator << (ostream&,classX);
and not
out o = ostream& operator << (ostream&,classX);
which prints the error messsage
190: error: invalid conversion from 'void*' to 'std::ostream& (*)(std::ostream&, classX)'
Depend on how you have overloaded the operator.
The signature (The type of the pointer that points to) of a function is:
RETURN_TYPE(*)(PARAMETERS_TYPES) if its a global function.
RETURN_TYPE (CLASS_NAME::*)(PARAMETERS_TYPES) if its a member function.
If you have a function called f and a function that gets a pointer to a function as parameter, f is passed as follows:
g(f) if f is a global function.
g(&CLASS_NAME::f) if f is a member function of CLASS_NAME class.
Note that function pointers and member function pointers are not compatible.
So if your operator is overloaded as a member function, like operator+= you should use the second version. If not, you should use the first.
I would simplify the assignment here. There is no need to specify the whole signature, since the correct overload can be inferred from the type on the left hand side.
#include <iostream>
using namespace std;
struct Foo
{
int x;
};
ostream& operator<< (ostream &a, const Foo& b)
{
return a << b.x;
}
typedef ostream& (*Func) (ostream &, const Foo&);
int main() {
Func func = &operator<<;
(*func)(cout, Foo{42});
}