I have 2 classes, Edge and Point. Edge contains Point P1 and Point P2 as private memebers. Edge has accessor functions

Point getP1()
{
return P1;
}

and the same for P2.

Point has << overloaded -

ostream & operator << (ostream &output, Point &p);

I am trying to overload << for Edge:

ostream & operator << (ostream &output, Edge &e);

this works fine:

ostream & operator << (ostream &output, Edge &e)
{
Point x = e.getP1();
Point y = e.getP2();

output << "P1: " << x << " P2: " << y;

return output;
}

but this doesn't work:

ostream & operator << (ostream &output, Edge &e)
{
output << e.getP1() << " " << e.getP2();
return output;
}

The compiler says "Error: no match for operator << in output << Edge::getP1()()"

First, why are there two sets of parentheses in the compilers message?

Second, why does this happen?

Thanks!

Dave

Point is not a POD (plain old data) type so you must either create overload << operator for it too or print each part separately

struct Point
{
  int x, y;
};

...
ostream & operator << (ostream &output, Edge &e)
{

    Point p1, p2;
    p1 = e.getP1();
    p2 = e.getP2();
   output << p1.x << " " << p1.y << " " << p2.x << " " << p2.y;
   return output;
}

or

struct Point
{
  int x, y;

};
ostream & operator << (ostream &output, Point &p)
{
   output << p.x << " " << p.y;
  return output;
}

...
ostream & operator << (ostream &output, Edge &e)
{

   output << e.getP1() << " " << e.getP2();
   return output;
}

In the original post I mentioned that I have already overloaded << for Point. And also since the operator<< has to be public (I could make it friend, but i chose not to), it has to look like this

ostream & operator << (ostream &output, Point &p)
{
output << p.getX() << " " << p.getY();
return output;
}

Is there anything else I can check??

>>In the original post I mentioned that I have already overloaded << for Point.
Yes you did and I missed it.

>>Is there anything else I can check??
don't know without seeing the entire code. Try my first suggestion to see if that compiles.

Ok I made a simple demo program that does exactly the same thing, now I get a different error though:

In geom_Edge.h (on this line "geom_Point P1")
error: field P1 has incomplete type

geom_Point.h

#include <iostream>
using namespace std;

class geom_Point
{
	double x;
	double y;
	double z;
public:
	double getX();
	double getY();
	double getZ();
	
	//default constructor
	geom_Point()
	{
	
	}

};

ostream & operator << (ostream &output, geom_Point &p);

geom_Point.cpp

#include "geom_Point.h"

double geom_Point::getX()
{
	return x;
}

double geom_Point::getY()
{
	return y;
}

double geom_Point::getZ()
{
	return z;
}


ostream & operator << (ostream &output, geom_Point &p)
{
	output << p.getX() << " " << p.getY();
	return output;
}

geom_Edge.h

#include <iostream>
using namespace std;

class geom_Point; //forward declaration

class geom_Edge
{
	geom_Point P1;
	geom_Point P2;
public:
	geom_Point getP1();
	geom_Point getP2();
	//default constructor
	geom_Edge()
	{

	}
};

ostream & operator << (ostream &output, geom_Edge &e);

geom_Edge.cpp

#include "geom_Edge.h"

ostream & operator << (ostream &output, geom_Edge &e)
{
	output << e.getP1() << " " << e.getP2();
	return output;
}

geom_Point geom_Edge::getP1()
{
	return P1;
}

geom_Point geom_Edge::getP2()
{
	return P2;
}

forward declarations only allow you to declare pointers to the class. If you want to declare an actual object then you need to include the entire header so that the compiler knows that the class looks like. Maybe this will work -- make P1 and P2 pointers in the .h file, then move the class constructor to the *.cpp file where you can allocate memory for them. You also have to change the get functions.

#include <iostream>
using namespace std;

class geom_Point; //forward declaration

class geom_Edge
{
	geom_Point* P1;
	geom_Point* P2;
public:
	geom_Point getP1();
	geom_Point getP2();
	//default constructor
};

ostream & operator << (ostream &output, geom_Edge &e);
#include "geom_Edge.h"

// class constructor
geom_Edge::geom_Edge()
{
    P1 = new geom_Point;
    P2 = new geom_Point;
}

ostream & operator << (ostream &output, geom_Edge &e)
{
	output << e.getP1() << " " << e.getP2();
	return output;
}

geom_Point geom_Edge::getP1()
{
	return *P1;
}

geom_Point geom_Edge::getP2()
{
	return *P2;
}

Sorry, I don't know why I used a forward declaration. SInce geom_Edge is not used in geom_Point, I can simply #include "geom_Point.h" in geom_Edge like so:

geom_Edge.h

#include <iostream>
using namespace std;

#include "geom_Point.h"

class geom_Edge
{
	geom_Point P1;
	geom_Point P2;
public:
	geom_Point getP1();
	geom_Point getP2();
	//default constructor
	geom_Edge()
	{

	}
};

ostream & operator << (ostream &output, geom_Edge &e);

NOW I am back to the << problem (phew, i was hoping it wouldn't just go away hahaha)

Try it with that geom_Edge.h and see what you get.

error: no match for 'operator<<' in 'output << ((geom_Edge*)e)->geom_Edge::getP1()'

using VC++ 2008 Express I didn't get any errors or warnings on that code. I created a new project, added the four files to it, created my own main() which was an empty function, and it compiled ok.

Ah I forgot to mention - neither do I!! I am trying to compile it with g++ (through KDevelop) because I have to make a linux static library (.a) file. I thought that g++ was much stricter about some things than VS. Can you try it on linux? I've tried it on 2 machines and got the same error both times.

-Dave

>>Can you try it on linux?
No -- I don't do linux :)

When I bump up the compiler's warning level I get these warnings

geom_Edge.cpp
d:\dvlp\test4\test4\geom_edge.cpp(7) : warning C4239: nonstandard extension used : 'argument' : conversion from 'geom_Point' to 'geom_Point &'
        A non-const reference may only be bound to an lvalue
d:\dvlp\test4\test4\geom_edge.cpp(7) : warning C4239: nonstandard extension used : 'argument' : conversion from 'geom_Point' to 'geom_Point &'
        A non-const reference may only be bound to an lvalue
geom_Point.cpp

Maybe that is what g++ is talking about ?

GOT IT!! I had to make the accessor functions const!

geom_Point getP1() const;

weird... why do you not have to do that in VS?

This article has been dead for over six months. Start a new discussion instead.