Why cannot compiler find operator<<

Why cannot compiler find operator<<?? Where is the compiler looking into to find the definition of operator<< when it encounters the line
cout <<f.some_func()<<endl;

The error:

error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘std::vector<std::vector<int> >’)
cout <<f.some_func()<<endl;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  
#include <iostream>
#include <string>
#include<vector>
using namespace std;

struct Bar
{
   int y;
};

class Foo
{
  int x;
  friend ostream & operator<<(ostream & os, Foo& f)
  {
      os << "Foo: " << f.x << endl;
      return os;
  }
  friend ostream & operator<<(ostream & os, Bar& b)
  {
      Foo f;
      os << "Bar b.y: " << b.y << endl;
      os << "Bar f.x: " << f.x << endl;

      return os;
  }
  friend ostream & operator<<(ostream & os, vector<vector<int> >& vec ){
      os << 5;
      return os;
  }

public:
  Foo(int x = 10):x{x}{}
  vector<vector<int> > some_func(){
    vector<vector<int> > abc(3, vector<int>(3));
    int x = 900;
    return abc;
  }

};


int main()
{
  Bar b { 1 };
  Foo f{ 13 };
  cout << f << endl;
  cout <<f.some_func()<<endl;
  return 0;
}
You do ask:
1
2
3
4
5
6
7
8
#include <iostream>
#include <vector>

int main() {
  std::vector<std::vector<int>> gaz;
  std::cout << gaz; // What should happen here?
  return 0;
}


You do define some output operators inside class Foo.
Are they members of Foo, or standalone functions?
Should they be visible in the global scope?

Why does an operator that has nothing to do with class Foo claim to be friend of Foo?
Avoid friends.
Where is the compiler looking into to find the definition of operator<< when it encounters the line cout <<f.some_func()<<endl;


It is looking in the namespace of its arguments (which is namespace std for both arguments) and in the current namespace (which is the global namespace). It is also looking for friends defined inside its arguments.

Friend operators are not exported to the global namespace -- which is normally what you want, and is probably the main reason friends are used in C++ -- but in this case, this prevents your program from compiling because the operator<< you want to be called is *not* for the class it's defined in.

Minimal fixes are to
1. define your operator<< for vectors outside the class Foo definition (and change its argument to take a const reference to the vector)
2. keep it where it is and add just a declaration outside the class definition (and change its argument to take a const reference to the vector)
Last edited on
@Cubbi, I made oprator<< as free function and add new function wrapper(). This will again cause error.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

#include <iostream>
#include <string>
#include<vector>
using namespace std;

struct Bar
{
   int y;
};

class Foo
{
  int x;
  friend ostream & operator<<(ostream & os, Foo& f)
  {
      os << "Foo: " << f.x << endl;
      return os;
  }
  friend ostream & operator<<(ostream & os, Bar& b)
  {
      Foo f;
      os << "Bar b.y: " << b.y << endl;
      os << "Bar f.x: " << f.x << endl;

      return os;
  }


public:
  Foo(int x = 10):x{x}{}
  vector<vector<int> > some_func(){
    vector<vector<int> > abc(3, vector<int>(3));
    int x = 900;
    return abc;
  }
  void wrapper(){
    cout << this->some_func() << endl;
  }

};

ostream & operator<<(ostream & os, vector<vector<int> > const&  vec ){
    os << 5;
    return os;
}


int main()
{
  Bar b { 1 };
  Foo f{ 13 };
  cout << f << endl;
  //cout << b << endl;
  cout <<f.some_func()<<endl;
  return 0;
}
and add new function wrapper(). This will again cause error.

The call inside wrapper() can't compile because that's line 38, and your operator<< for vectors is not defined until line 43. Move that definition above class Foo and it will compile

It really isn't a good idea defining operators for types you did not write yourself (such as std::vector) - with some care you can get it to work in many situations, but not all. If you really want the result of some_func() to be streamable, return a type that you control.
Last edited on
@Cubbi, Oh!!! My bad!! Btw lets say I have the following relationship
Shape<---Triangle<---IsoTriangle and Triangle<--AcuteTriangle
Here Shape and Triangle are abstract classes and IsoTriangle is a concrete class.
Now, I have a wrapper function with vector<vectror<int>> return. Now, I wan to overload operator<< but the code is same for every class. Where should I put the code so that its visisble for all classes?
> Where should I put the code so that its visisble for all classes?

In the base class, perhaps.
Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <vector>

struct base
{
    struct vec2d // wrapper class to hold the vector
    {
        std::vector< std::vector<int> > data ;

        // this operator can be found only via ADL (good idea)
        friend std::ostream& operator<< ( std::ostream& stm, const vec2d& v2d )
        {
            for( const auto& row : v2d.data )
            {
                for( int v : row ) stm << v << ' ' ;
                stm << '\n' ;
            }
            return stm << "\n\n" ;
        }
    };

    // Guideline #1: Prefer to make interfaces non-virtual
    // see: http://www.gotw.ca/publications/mill18.htm
    vec2d some_func() const { return some_func_impl() ; }
    void print_some_func_result() const { std::cout << some_func() << '\n' ; }

    // ...

    // Guideline #2: Prefer to make virtual functions private
    // see: http://www.gotw.ca/publications/mill18.htm
    private: virtual vec2d some_func_impl() const
    { return { { {1,2,3}, {4,5,6}, {7,8,9} } } ; }
};

struct derived : base
{
    private: virtual vec2d some_func_impl() const override
    { return { { {1,2,3,4}, {5,6,7,8}, {2,3,4,5}, {6,7,8,9} } } ; }

    // ...
};

int main()
{
    const base bb ;
    const derived dd ;

    const base& b1 = bb ;
    const base& b2 = dd ;

    b1.print_some_func_result() ;
    b2.print_some_func_result() ;
 }

http://rextester.com/BXDS86094
@JLBorges, The function that I want is not a friend since I am not accessing any private members. So, if I want them to be seen by all the other classes where should I place them?
This is what I did. After defining the base class I put the free function definition. Now I inherit that class and make another abstract class lets say child_1. Now when I inherit child_1 and make a concrete class child_2 and call operator<< the compiler says multiple definitions but my definitions are only inside the base class.
The function that I want is not a friend since I am not accessing any private members

That's not why he made it a friend

After defining the base class I put the free function definition ... the compiler says multiple definitions but my definitions

without code we can only guess, and my guess is that you have a function in a header file that needs to be marked inline
Topic archived. No new replies allowed.