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.
Related
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.
I have a class that reads parts of a binary file into variables of different types.
class Foo {
public:
size_t getSizeT();
float getFloat();
std::string getString();
private:
std::ifstream stream;
};
Now I'd like to implement the stream extraction operator as described in this answer.
class Foo {
public:
Foo &operator>>(Foo &foo, size_t &value);
Foo &operator>>(Foo &foo, float &value);
Foo &operator>>(Foo &foo, std::string &value);
private:
std::ifstream stream;
};
The code fails to compile with this error message: error C2804: binary 'operator >>' has too many parameters. How to properly override the stream extraction operator? It should distinguish between types and be chainable.
As free function, operator signature should be:
Foo& operator >>(Foo& foo, size_t& value);
As member function (your case), it should be:
Foo& operator >>(size_t& value);
If an instance of your class is the source of the data, then you have two ways of writing the input operator function: Either as a stand-alone global function taking two arguments, the instance of your class and the destination object. Or you write it as a member-function of your class, and then it takes only a single argument which is the destination.
So for a global function you write e.g.
class Foo { ... };
Foo& operator>>(Foo& foo, int& i)
{
// Get an integer and writes to `i` here
return foo;
}
For a member function you write e.g.
class Foo
{
public:
...
Foo& operator>>(int& i)
{
// Get an integer and writes to `i` here
return *this;
}
};
The reason I think you wrote the operator wrong, is because you can write the first version, using global functions, as friend function inline inside a class, and you have seen that before mistaking between the difference between a friend function and a member function.
You use friend functions like
class Foo
{
public:
...
// Notice the keyword `friend`
friend Foo& operator>>(Foo& foo, int& i)
{
// Get an integer and writes to `i` here
return foo;
}
};
The difference between a member function and a friend function is subtle but very important.
I have a derived basic_ostream class and an inline modifier (similar to setw). My stream class should also inherit all the operator << behavior from its parent. I get different compiler errors depending on whether I use the "using" keyword or not:
#include <iostream>
struct modifier { };
template <typename C, typename T=std::char_traits<C> >
struct mystream : public std::basic_ostream<C, T>
{
// this is where the trouble is
using std::basic_ostream<C, T>::operator <<;
inline mystream & operator << (const modifier & mod)
{
// ...custom behavior...
return *this;
}
};
int main()
{
mystream<char> foo;
modifier m;
foo << "string"; // this fails if the using is present
foo << 123; // this fails if the using is absent
foo << m;
}
When I put the using directive in, the compiler is confused about the "string" output, and if I comment it out, it gets confused about the integer 123 output, in both cases giving me "error: ambiguous overload for 'operator<<'". I have the problem with both g++ 4.2.1 and g++4.8. What's the right way forward here?
Rather then inherit from std::basic_ostream, won't it be sufficient to just re-implement << for your modifier struct using a regular stream:
std::ostream & operator << (std::ostream &stream, const modifier & mod)
{
// ...custom behavior...
return stream;
}
Your solution seems overcomplicated, but I think the actual error you get comes from your overload of << - it has to accept two arguments (first argument being reference to stream itself).
Without the using, it is clear: the compiler will not find any
of the member overloads of <<, because your function hides
them. The << is a member, so without the using, it
disappears. The << is not a member, so it still works.
When you add the using: all of the member overloads are
visible, as if they were members of your class. And
"string" will be converted to a char const*. The overload
that the compiler is trying to resolve is:
operator<<( mystream<char>, char const* ).
Now consider some of the overloads to be considered:
std::ostream& mystream::operator<<( void const* );
std::ostream& mystream::operator<<( bool );
std::ostream& operator<<( std::ostream&, char const* );
For the first argument (foo, a mystream), the first two
functions are both better matches than the third (since they are
an exact match); for the second argument (the string literal),
the third function is a better match. Thus: ambiguous.
More generally, there are several problems with your code.
Fundamentally, you do not add << operators by deriving. As
you see, it doesn't work. Perhaps more significantly, something
like:
foo << 123 << m;
will not work, because foo << 123 returns a std::ostream&,
not a mystream, and there is no << which will work with an
std::ostream& and a modifier. You add << operators by
defining new free functions:
std::ostream&
operator<<( std::ostream& dest, modifier const& other )
{
// ...
return *this;
}
If you need additional data to format, you use xalloc and
iword or pword to get it, e.g. to define a manipulator:
static int Modifier::modIndex = std::ostream::xalloc();
class mod1
{
int myModifier;
public:
mod1( int m ) : myModifier( m ) {}
friend std::ostream& operator<<( std::ostream& dest,
mod1 const& mod )
{
dest.iword( modIndex ) = myModifier;
return *this;
}
};
You then access dest.iword( modIndex ) to get this information
in the output routine.
iword() returns a long&, different for each instance of your
stream (and for each different index you use).
If you need more information, you can use pword instead of
iword—pword returns a reference to a void*. If you
want use it to point to dynamically allocated memory, don't
forget to register a callback to delete it (using
ios_base::register_callback).
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<<.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
When should you use 'friend' in C++?
There is a detailed explanation here, but I would like to know what is the practical use of Friend function.
How I can decide when I should go with a friend function rather than a member function?
In most cases, friend declarations are a code-smell since it breaks encapsulation.
Developers often use friend for a quick-fix to a problem. However a good starting design or some refactoring (more often more than less) exclude the necessity for it.
EDIT:
Even in #Darhuuk's example, a friend declaration is not needed. You can have getters for the specific fields you want to print.
You would use a friend when the function needs to be a non-member, but also needs access to class members.
Common examples where you need a non-member function are:
An API that requires non-member functions; for example, boost::intrusive_ptr requires that you implement intrusive_add_ref() and intrusive_release() as non-member functions.
Overloading a binary operator where your type need to be the right-hand operand; for example operator<<(ostream&, my_type const &).
Overloading a binary operator where you want the left-hand side to be convertible to your type; for example, if your class is constructible from int, then 5 + my_type will work if you define a non-member operator+(my_type const&, my_type const&);, but not if you define a member my_type::operator+(my_type const &) const;.
Whether any of these needs to be friends depends on whether they can do their job using the class's public interface; for example, you could add a public print(ostream&) member that operator<< could use, and a public operator+= member that operator+ could use.
As an example of implementing operator+ in terms of operator+=:
my_type & my_type::operator+=(my_type const & rhs)
{
// do addition here
return *this;
}
// The first operand is passed by value, giving a modifiable copy
my_type operator+(my_type lhs, my_type const & rhs)
{
return lhs += rhs;
}
The simplest use case would probably be when overloading the stream output operator for a custom class.
For example, take a look at the following code (shamelessly copied from here). In this case the use of friend allows the non-class method to access the private fields of class, thus preventing the need to code several get methods (which otherwise you might not even want to create).
#include <iostream>
#include <cstring>
using namespace std;
class MyClass {
// now private
char name[80];
int areacode;
int prefix;
int num;
public:
MyClass(char *n, int a, int p, int nm)
{
strcpy(name, n);
areacode = a;
prefix = p;
num = nm;
}
friend ostream &operator<<(ostream &stream, MyClass o);
};
ostream &operator<<(ostream &stream, MyClass o)
{
stream << o.name << " ";
stream << "(" << o.areacode << ") ";
stream << o.prefix << "-" << o.num << "\n";
return stream;
}
int main() {
MyClass a("T", 1, 5, 1);
MyClass b("A", 3, 5, 5);
MyClass c("T", 2, 5, 9);
cout << a << b << c;
return 0;
}