Proper way to Overload operator<<

I've tried numerous ways of overloading operator<< for numerous classes, but I always seem to get some sort of compiler error.

I try:
1
2
3
4
5
6
7
8
template <class T>
std::ostream& ArrayList<T>::operator<<(std::ostream& s, const ArrayList<T>& a)
{
    for(int i = 0; i < a.getSize(); i++)
        s << a[i];

    return s;
}


and I get the following error:

'std::ostream& ArrayList<T>::operator<<' must take exactly one argument.


So I remove the const ArrayList<T>& arg, resulting in something like this:

1
2
3
4
5
std::ostream& operator <<(std::ostream& s)
{
    for(int i = 0; i < size; i++)
        s << accounts[i] << std::endl;
}


and get an error like this:

no match for 'operator<<' (operand types are 'std::ostream' and 'Account')


I finally resort to defining all of my overloads outside of the classes and making them all "friends," resulting in something like this:

1
2
3
4
5
6
7
8
9
friend std::ostream& operator <<(std::ostream& s, const Account& h)
{
    s << "Login: " << h.getUser() << std::endl;
    s << "Directory: " << h.getHome() << std::endl;
    s << "Shell: " << h.getShell() << std::endl;
    s << "Gecos: " << h.getGecos() << std::endl;

    return s;
}


and nearly everywhere I use an overloaded << operator I get an error like this:

undefined reference to `operator<<(std::ostream&, ArrayList<char> const&)'


Can you help me figure out what I'm doing wrong?
Last edited on
Make sure your testcase is self-contained and actually reproduces the problem



First snip, I guess that you are defining it as a member function.
So you end with 3 objects: the stream `s', the arraylist `a' and the arraylist *this

Second snip, I don't believe that the error message refers to that snip, but to its usage.
You were trying to do, by instance, std::cout << foo; but the code is for doing foo << std::cout;

Third snip, ¿no more a template?
about undefined reference http://www.cplusplus.com/forum/general/113904/

Four snip, too much blank to fill.
1. Operator<< should not be a member:
http://en.cppreference.com/w/cpp/language/operators#Canonical_implementations

2. Avoid making friends. If your type T has sufficient public interface, then non-friends can extract necessary values.


It seems that you need a templated operator<< the ArrayList family of types and a concrete operator<< for Account as (presumably) you try to print an Arraylist<Account> object.
How do I overload the operator without making it either a member or a friend?
I looked at the link kesk gave me, and it didn't exactly help. I know what might cause a linker error now, but I always put class definitions in the header files. I also included the header file in all of my other files. What else might cause a linker error.
How do I overload the operator without making it either a member or a friend?

The overloaded operator needs to define both arguments (on the right and left side of <<):
ostream & operator<<(ostream &os, const Account &acct);

Now if there aren't sufficient public interfaces to write this code then make it a passthrough to a method:
1
2
3
ostream & operator<<(ostream &os, const Account &acct) {
    return acct.output(os);
};


How do I know if I don't have sufficient public interfaces?
The overloaded operator needs to define both arguments (on the right and left side of <<):


I've figured that much out, but that doesn't help me fix the compiler error I get when I don't include the friend modifier. The compiler assumes that it's a member function and demands it only have one argument.
It shouldn't be a member function. You want something like this:
1
2
3
4
class MyClass {
    ....
};
ostream & operator<<(ostream &os, const MyClass &);


How do I know if I don't have sufficient public interfaces?

Now that the << operator is not a member of the class it can only access the public members. So can it access everything it needs to? If not then you can do the pass-through method that I mentioned.
Topic archived. No new replies allowed.