Relation between ostream insertion operator and its non-member overload - c++

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.

Related

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.

How to override ostream << operator for already defined type

I'm currently working on a port of an existing library which makes use of ostream to write to a terminal.
The ostream was derived as part of the port.
The ostream derivative class used is defined as so:
class owstream: public std::ostream {
public:
CTerminal * output;
giac::context * contextptr;
owstream(CTerminal *, giac::context * contextptr , int = 0);
virtual ~owstream();
};
This is used to output some data, typically integers and doubles.
The problem is that the platform I'm working on has a buggy double print routine that causes kernel crash.
So in some cases, if I do:
ostream* mystream = new ostream(...);
(*mystream) << 1.23456
kaboom
so, I tried to override the << operator for certain type, like so:
ostream* GetStream() { return = new MyOStream(...); }
....
ostream* mystream = GetStream()
mystream << 1.23456;
Unfortunately, the operator<< member in ostream isn't virtual so if I created an overridden operator<< member would never be called.
I tried to extend it with something like:
class owstream: public std::ostream {
friend std::ostream& operator<<(std::ostream& out, double val);
public:
CTerminal * output;
giac::context * contextptr;
owstream(CTerminal *, giac::context * contextptr , int = 0);
virtual ~owstream();
};
extern std::ostream& operator<<(std::ostream &out, double val);
But this causes compilation error in regards to operator << being ambiguous, as obviously this is a type already handle by the base iostream class.
I'm starting to wonder if this is at all possible.
How would you implement the << operator to override the behaviour when given a particular, already handled type ?
The aim being able to do something like:
cout << 1.234567
not crashing (I obviously wouldn't be using cout, but GetStream() as defined above, could very well return cout)
I see three problems with your current approach/implementation.
Problem #1
Even if you were to successfully get it to use std::ostream as the first parameter and return value it would not work correctly. The problem stems mainly from returning an ostream from the overloaded operator<<. After the first value has been sent to the owstream all subsequent values get sent to the returned ostream. This puts you right back where you started with the original problem. In order to for this to work properly you need to take owstream as the first parameter and return an owstream in the overloaded operator<<.
Problem #2
Another problem is owstream is implicitly convertible to std::ostream. Depending on how owstream is used in your project there is a possibility that the overloads you provide may not make a difference in certain situations. For instance if an object of type owstream is passed to a function that accepts a std::ostream you may end up encountering the problem you are currently experiencing. You can prevent this from happening by using private inheritance. This will prevent any implicit use of owstream as a std::ostream. Using private inheritance also has the benefit of preventing you from unknowingly using functions in std::ostream which may lead you back to your original problem. For instances where a std::ostream is absolutely necessary you can use an accessor function to explicitly retrieve a reference to it.
Problem #3
The last issue is that std::ostream includes an overload of operator<< that handles std::ostream specific IO manipulators such as std::endl. If you do not provide an overload to specifically handle these the one in std::ostream gets used and once again you end up right back where you started. If you use private inheritance described above and do not provide an overload to handle the manipulators it will fail to compile.
Solution
The solution below is similar to the one provided by JRG and includes the accessor function and overloads for double, float, and std::ostream IO manipulators. It is a complete working example and uses the stream buffer from std::cout for simplicity. I included the overload for float as the deficient library implementation may a similar issue with them. It also uses private inheritance to prevent implicit conversions to std::ostream.
I tested it on VC++10 and GCC 4.7.2. You may need to make some adjustments depending on how compliant your compiler and libraries are.
#include <ostream>
#include <iostream>
#include <sstream>
class owstream : private std::ostream
{
public:
owstream(std::streambuf* sb)
: std::ostream(sb)
{}
// Template based operator...ohhhhhh ahhhhh.
template <typename T>
friend owstream& operator<<(owstream&, const T&);
// Additional overload to handle ostream specific io manipulators
friend owstream& operator<<(owstream&, std::ostream& (*)(std::ostream&));
// Accessor function to get a reference to the ostream
std::ostream& get_ostream() { return *this; }
};
template <typename T>
inline owstream&
operator<<(owstream& out, const T& value)
{
static_cast<std::ostream&>(out) << value;
return out;
}
// overload for double
template <>
inline owstream&
operator<<(owstream& out, const double& value)
{
std::stringstream ss;
ss << value;
return out << ss.str();
}
// overload for float
template <>
inline owstream&
operator<<(owstream& out, const float& value)
{
std::stringstream ss;
ss << value;
return out << ss.str();
}
// overload for std::ostream specific io manipulators
inline owstream&
operator<<(owstream& out, std::ostream& (*func)(std::ostream&))
{
static_cast<std::ostream&>(out) << func;
return out;
}
int main()
{
owstream ows(std::cout.rdbuf());
ows << std::endl;
ows << "hello " << 1.0 << " " << 2.0f << std::endl;
}
What about something like this:
template <typename T>
owstream& operator<<(owstream&, const T&);
template <typename T>
inline owstream&
operator<<(owstream& os, const T& val)
{
std::ostream& stdos = static_cast<std::ostream&>(os);
stdos << val;
return os;
}
template <>
inline owstream&
operator<<(owstream& os, const double& val)
{
std::stringstream ss;
ss << val;
os << ss.str();
return os;
}

derived basic_ostream: "using" keyword and ambiguous overload for operator <<

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).

operator << must take exactly one argument

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<<.

Friend function - practical use? [duplicate]

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;
}