2

I have a class entry and an ostream& operator << overwritten for it. I also have an auxiliary class cursor and a type conversion operator entry(). Then, in my main() function I have the following expression:

cout << data[4];

where data[4] is a cursor, but compilation fails with

error: invalid operands to binary expression

What I want is for a compiler to convert data[4] to entry and to use its << operator. Is there any way to call this ostream operator in an aforementioned way without having to add special methods to entry?

Here are some pieces of code:

    class entry
    {
        friend class cursor;
        /*here comes some data*/

    public:    

        friend ostream& operator << (ostream& out, const entry& a);
    };

    class cursor
    {
        database* data_;
        size_t ind_;
        friend class entry;
        friend class database;

    public:
        cursor (database* a, size_t ind);
        cursor (const cursor& a);
        void operator= (const  entry x);
        void operator= (const cursor a);

        operator entry();           //type conversion
    };

and here is what I use in main():

    cout << data[4];
M.M
  • 138,810
  • 21
  • 208
  • 365

1 Answers1

6

When you write:

class entry
{
    // ...
    friend ostream& operator << (ostream& out, const entry& a);
};

Although this declares operator<< in the enclosing scope, the name lookup rules say that name lookup in that scope does not actually find this function! (Because it has only been declared via friend).

If a function has only been declared via friend, then the only way it can be found is via argument-dependent lookup. See this thread for more detailed explanation of the lookup rules.

The function would be found by:

entry e;
cout << e;

because ADL sees that there is an argument of type entry and so it searches functions that are associated with entry (including friends declared there).

However, cursor c; cout << c; does not include entry in its search list (even though a conversion from cursor to entry exists).


To fix this you need to provide a non-friend declaration of the operator, that is visible at the point of main. For example:

ostream& operator << (ostream& out, const class entry& a);

class entry
{
    // ...
    friend ostream& operator << (ostream& out, const entry& a);
};

NB. I chose to put the declaration before the class instead of after, because this is also the best way to solve the template friends problem.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365