I'm trying to overload the << and >> operators for a polygon class and a derived triangle class. The problem is that my compiler is returning the following error:
error: undefined reference to `operator<<(std::ostream&, triangle const&)'
I am fairly certain that I did define the above operator however. I have the following line in my triangle.h file:
std::ostream & operator << (std::ostream & os, triangle const&);
This problem occurs specifically for the triangle class. When I remove the line trying to output a triangle, my program works correctly. There is no problem outputting a polygon. What is causing this problem and how do I fix it? Is it a problem with my include hierarchy?
I think the relevant files are main.cpp, triangle.h, and triangle.cpp but I included a full copy of my code below in case the error is caused by something else. Thank you for your help and patience.
main.cpp
#include <iostream>
#include "triangle.h"
using namespace std;
int main()
{
triangle t (vertex (0, 0), vertex (5, 0), vertex (0, 5));
triangle l (t);
cout << l[0] << endl;
cout << "L: " << l << endl; //not working
polygon p;
p.add (vertex (0,0));
cout << "P: " << p << endl; //working
return 0;
}
triangle.h
#include "polygon.h"
#include <iostream>
class triangle : public polygon
{
public:
triangle(vertex = vertex(), vertex = vertex(), vertex = vertex());
triangle(const triangle &);
double area() const;
vertex operator[](size_t i) const;
private:
size_t size() const;
void add(vertex iv);
std::vector<vertex> v;
};
std::ostream & operator << (std::ostream & os, triangle const&);
std::istream & operator >> (std::istream & is, triangle & t);
triangle.cpp
#include "triangle.h"
#include <math.h>
#include <cassert>
triangle::triangle(vertex ta, vertex tb, vertex tc)
{
v.push_back(ta);
v.push_back(tb);
v.push_back(tc);
}
triangle::triangle(const triangle & t)
{
v=t.v;
}
double triangle::area() const
{
double a=sqrt((v[0].x-v[1].x)*(v[0].x-v[1].x)+(v[0].y-v[1].y)*(v[0].y-v[1].y));
double b=sqrt((v[1].x-v[2].x)*(v[1].x-v[2].x)+(v[1].y-v[2].y)*(v[1].y-v[2].y));
double c=sqrt((v[2].x-v[0].x)*(v[2].x-v[0].x)+(v[2].y-v[0].y)*(v[2].y-v[0].y));
double s=((a+b+c)/2);
return sqrt(s*(s-a)*(s-b)*(s-c));
}
vertex triangle::operator[] (std::size_t i) const
{
assert (i<3);
return v[i];
}
inline std::ostream & operator << (std::ostream & os, triangle const & t)
{
std::cout << "test" << std::endl;
return os << t[0];
}
std::istream & operator >> (std::istream & is, triangle & t)
{
vertex vx;
for (size_t i = 0; i < 3; ++i)
{
is >> vx.x >> vx.y;
//t.v.push_back(vx);
}
return is;
}
polygon.h
#include <iostream>
#include <vector>
#include "vertex.h"
class polygon
{
public:
// pre:
// post: empty polygon created
polygon();
// pre:
// post: polygon created and initialized to given polygon source
polygon(const polygon & source);
// pre:
// post: return number of vertices in this polygon
std::size_t size() const;
// pre: 0 <= i < size()
// post: return vertex i in this polygon
vertex operator[](size_t i) const;
// pre:
// post: vertex is added to this polygon
void add(const vertex & v);
private:
std::vector<vertex> v;
};
std::ostream & operator << (std::ostream & os, const polygon & p);
std::istream & operator >> (std::istream & is, polygon & p);
polygon.cpp
#include <cassert>
#include "polygon.h"
polygon::polygon()
{
v = std::vector<vertex> ();
}
polygon::polygon(const polygon & p)
{
v = p.v;
}
std::size_t polygon::size() const
{
return v.size();
}
vertex polygon::operator[] (std::size_t i) const
{
assert(i < size());
return v[i];
}
void polygon::add(const vertex & vx)
{
v.push_back(vx);
}
std::ostream & operator << (std::ostream & os, const polygon & p)
{
for (std::size_t i = 0; i < p.size(); ++i)
os << p[i] << " ";
return os;
}
std::istream & operator >> (std::istream & is, polygon & p)
{
std::size_t n;
vertex vx;
is >> n;
for (size_t i = 0; i < n; ++i)
{
is >> vx.x >> vx.y;
p.add(vx);
}
return is;
}
vertex.h
#include <iostream>
struct vertex
{
double x, y;
vertex(double ix = 0.0, double iy = 0.0)
{
x = ix;
y = iy;
}
};
std::ostream & operator << (std::ostream & os, const vertex & v);
vertex.cpp
#include "vertex.h"
std::ostream & operator << (std::ostream & os, const vertex & v)
{
os << "(" << v.x << ", " << v.y << ")";
return os;
}
Here's your problem:
// triangle.cpp
inline std::ostream & operator << (std::ostream & os, triangle const & t)
^^^^^^
Inline functions must be defined in all translation units that use them, and this is only defined in one. Either remove inline, or move the definition into the header to make it available anywhere its used.
Related
I have a Class called "Vector". It consists of two private fields: std::vector<double> coordinates and int len. Methoddim() returns len.
I am overloading operator << like that:
friend std::ostream& operator<<(std::ostream& os, Vector& vec )
{
std:: cout << "(";
for ( int i = 0; i < vec.dim(); i++ ) {
if ( i != vec.dim()-1){
os << vec[i] << ", ";
} else {
os << vec[i];
}
}
os << ')';
return os;
}
An operator + like that:
friend Vector operator +(Vector& first, Vector& second)
{
if(first.dim() != second.dim()){
throw std::length_error{"Vectors must be the same size"};
}else {
Vector localVec(first.dim()); // same as {0,0,0...,0} - first.dim() times
for (int i = 0; i < first.dim(); i++){
localVec[i] = first[i] + second[i];
}
return localVec;
}
}
And operator [] like that:
double& operator[](int index)
{
return this->coordinates[index];
}
And here's the problem:
Vector x{1,2,4};
Vector y{1,2,3};
Vector z = x + y;
std:: cout << z; // it works perfectly fine - (2, 4, 7)
std:: cout << x + y; // it gives me an error
could not match 'unique_ptr<type-parameter-0-2, type-parameter-0-3>' against 'Vector'
operator<<(basic_ostream<_CharT, _Traits>& __os, unique_ptr<_Yp, _Dp> const& __p)
It seems to me that this error is related to parameter Vector& vec , but I don't know whether it's right and what should I do to fix it. If anyone could give me a hint (or tell me what I should read more about) - I would be very grateful.
Here's full code:
class Vector
{
private:
std::vector <double> coordinates;
int len;
public:
Vector(): len{0}, coordinates{} {};
Vector(std::initializer_list <double> coordinates_): len{static_cast <int>( coordinates_.size())}, coordinates{coordinates_} {}
Vector(int len) : len{len} {
for(int i = 0; i < len; i++){
coordinates.push_back(0);
}
}
int dim() const
{
return this->len;
}
double& operator[](int index)
{
return this->coordinates[index];
}
friend std::ostream& operator<<(std::ostream& os, Vector& vec )
{
std:: cout << "(";
for ( int i = 0; i < vec.dim(); i++ ) {
if ( i != vec.dim()-1){
os << vec[i] << ", ";
} else {
os << vec[i];
}
}
os << ')';
return os;
}
friend Vector operator +(Vector& first, Vector& second)
{
if(first.dim() != second.dim()){
throw std::length_error{"Vectors must be the same size"};
}else {
Vector localVec(first.dim());
for (int i = 0; i < first.dim(); i++){
localVec[i] = first[i] + second[i];
}
return localVec;
}
}
};
friend std::ostream& operator<<(std::ostream& os, Vector& vec)
This signature doesn't accept rvalues, and this is why the error happens for your temporary result here:
std:: cout << x + y;
Change the second parameter into const Vector& vec or provide an overload with an r-value reference parameter.
friend std::ostream& operator<<(std::ostream& os, const Vector& vec);
A temporary cannot bind to a non-const reference argument. You are missing const in at least two places. Most importantly here:
friend std::ostream& operator<<(std::ostream& os, const Vector& vec )
// ^^
And there should a const overload of operator[]
I'm having trouble with the syntax for a homework program. The prompt is to overload an inserter in such a way that it can properly execute the program fragment:
for (int i = 0; i < v.size(); ++i)
cout << v[i] << endl;
cout << endl;
So, this is what I have so far, but I still get an error at the cout << v[i] statement (Invalid operands to binary expression):
unsigned int seed;
struct node
{
int integer;
double value;
};
double random(unsigned int &seed);
void initialize_vector(vector<node> &v);
template<typename T>
void print_vector(const vector<T> &v);
template<typename T>
ostream &operator <<(ostream &out, const vector<T> &v);
template<typename T>
void output(ostream &out, const vector<T> &v);
int main()
{
vector<node> v(10);
initialize_vector(v);
print_vector(v);
return 0;
}
double random(unsigned int &seed)
{
const int MODULUS = 15749;
const int MULTIPLIER = 69069;
const int INCREMENT = 1;
seed = ((MULTIPLIER * seed) + INCREMENT) % MODULUS;
return double(seed) / double(MODULUS);
}
void initialize_vector(vector<node> &v)
{
for (int i = 0; i < v.size(); ++i)
{
v[i].integer = int (11 * random(seed));
v[i].value = double (11 * random(seed));
}
}
template<typename T>
void print_vector(const vector<T> &v)
{
for (int i = 0; i < v.size(); ++i)
cout << v[i] << endl;
cout << endl;
}
template<typename T>
ostream &operator <<(ostream &out, const vector<T> &v)
{
output(out, v);
return (out);
}
template<typename T>
void output(ostream &out, const vector<T> &v)
{
cout << v.integer;
cout << setprecision(2) << fixed << setw(6) << v.value;
}
I've tried passing node instead of T, along with passing with and without const references for the last 3 functions, so again I assume my syntax in the void output function is wrong somehow. Any help or points in the right direction would be greatly appreciated.
*Note: I can't change the ostream &operator function.
cout << v[i] << endl;
If v is a vector of node, then you need one more function to overload operator << for a node
ostream &operator <<(ostream &out, const node &n)
{
out << n.interger << " " << n.value;
return out;
}
Given a vector of coordinates corresponding to city locations on a grid, how can I generate every permutation of these point objects? I suspect there is a problem with using a user-defined class (Point, in my case) with the predefined function next_permutation.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Point
{
public:
double x, y;
Point(int x, int y);
friend ostream& operator<< (ostream &out, const Point &p);
};
Point::Point(int xCoord, int yCoord)
{
x = xCoord;
y = yCoord;
}
ostream& operator<< (ostream &out, const Point &p)
{
out << "(" << p.x << ", " << p.y << ")";
return out;
}
int main()
{
vector<Point> points = { {3,5}, {10,1}, {2,6} };
do
{
for (Point pt : points)
{
cout << pt << " ";
}
cout << endl;
} while (next_permutation(points.begin(), points.end()));
}
A couple of things,
first to use next_permutations the container must be sorted.
second to compare two custom objects for sort and next_permutations, you need to overload the < operator.
something like this should work:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
class Coords
{
public:
int x = 0;
int y = 0;
//This uses a simple lexicographical ordering, modify to suit your needs.
bool operator <( const Coords& rhs )
{
if ( x == rhs.x )
{
return y < rhs.y;
}
else
{
return x < rhs.x;
}
}
};
vector<vector<Coords>> GetPermutaions( vector<Coords>& vec )
{
vector < vector<Coords>> outVal ;
//if you can guarantee vec will be sorted this can be omitted
sort( vec.begin() , vec.end() );
do
{
outVal.emplace_back( vec );
} while ( next_permutation( vec.begin() , vec.end() ) );
return outVal;
}
One thing to remember, this function will leave vec in a sorted state. If you need the original state, create a copy of vec to do the permutations.
Ex snippet:
#include<iostream>
#include<vector>
#include<algorithm>
int main()
{
typedef std::vector<int> V; //<or_any_class>
V v;
for(int i=1;i<=5;++i)
v.push_back(i*10);
do{
std::cout<<v[0]<<" "<<v[1]<<" "<<v[2]<<" "<<v[3]<<" "<<v[4]<<std::endl;
}while(std::next_permutation(v.begin(),v.end()));
return 0;
}
I have this formatted string in an istream.
(5, -4)
Let say :
open parenthesis
an integer number
comma and space
another integer number
close parenthesis
I would like to know what is the best approach to extract both integers and validate the string formatting.
This is in a class like this :
class MyPoint
{
public:
MyPoint() = default;
~MyPoint() = default;
...
friend ostream & operator>>(ostream & lhs, MyPoint const & rhs);
...
private:
int x, y;
};
ostream & operator>>(ostream & lhs, MyPoint const & rhs) {
// ???
}
Many thanks to all.
Here is my header file
#ifndef MYPOINT_H
#define MYPOINT_H
#include <iostream>
using namespace std;
class MyPoint
{
public:
MyPoint() : mX{ 0 }, mY{ 0 } { ; }
MyPoint(int x, int y) : mX{ x }, mY{ y } { ; }
~MyPoint() = default;
int x() const { return mX; }
int y() const { return mY; }
void setX(int x) { mX = x; }
void setY(int y) { mY = y; }
MyPoint operator-() const { return MyPoint(-mX, mY); }
MyPoint operator+(MyPoint rhs) const { rhs.mX += mX; rhs.mY += mY; return rhs; }
MyPoint operator-(MyPoint rhs) const { rhs.mX = mX - rhs.mX; rhs.mY = mY - rhs.mY; return rhs; }
MyPoint operator*(MyPoint rhs) const { rhs.mX *= mX; rhs.mY *= mY; return rhs; }
MyPoint operator/(MyPoint rhs) const { rhs.mX = mX / rhs.mX; rhs.mY = mY / rhs.mY; return rhs; }
MyPoint operator%(MyPoint rhs) const { rhs.mX = mX % rhs.mX; rhs.mY = mY % rhs.mY; return rhs; }
friend MyPoint operator+(int lhs, MyPoint const & rhs);
friend MyPoint operator-(int lhs, MyPoint const & rhs);
friend MyPoint operator*(int lhs, MyPoint const & rhs);
friend MyPoint operator/(int lhs, MyPoint const & rhs);
friend MyPoint operator%(int lhs, MyPoint const & rhs);
friend ostream & operator<<(ostream & lhs, MyPoint const & rhs);
friend istream & operator>>(istream & lhs, MyPoint & rhs);
private:
int mX, mY;
};
#endif //MYPOINT_H
And here my source file
#include "MyPoint.h"
MyPoint operator+(int lhs, MyPoint const & rhs) {
return MyPoint(lhs + rhs.mX, lhs + rhs.mY);
}
MyPoint operator-(int lhs, MyPoint const & rhs) {
return MyPoint(lhs - rhs.mX, lhs - rhs.mY);
}
MyPoint operator*(int lhs, MyPoint const & rhs) {
return MyPoint(lhs * rhs.mX, lhs * rhs.mY);
}
MyPoint operator/(int lhs, MyPoint const & rhs) {
return MyPoint(lhs / rhs.mX, lhs / rhs.mY);
}
MyPoint operator%(int lhs, MyPoint const & rhs) {
return MyPoint(lhs % rhs.mX, lhs % rhs.mY);
}
ostream & operator<<(ostream & lhs, MyPoint const & rhs) {
return lhs << "(" << rhs.mX << "," << rhs.mY << ")";
}
istream & operator >> (istream & lhs, MyPoint & rhs) {
return lhs >> "(" >> rhs.mX >> "," >> rhs.mY >> ")"; // HERE is the compiling error
}
And finally, the tests in the main
MyPoint p1, p2(2, -2);
cout << p1 << endl;
cout << p2 << endl;
With this file, I got this error :
Error C2679 binary '>>': no operator found which takes a right-hand operand of type 'const char [2]' (or there is no acceptable conversion)
For situations like this, I've often found it handy to define an overload of operator>> to read a predefined string from a stream:
std::istream &operator>>(std::istream &is, char const *pat) {
char ch;
while (isspace(static_cast<unsigned char>(is.peek())))
is.get(ch);
while (*pat && is && *pat == is.peek() && is.get(ch)) {
++pat;
}
// if we didn't reach the end of the pattern, matching failed (mismatch, premature EOF, etc.)
if (*pat) {
is.setstate(std::ios::failbit);
}
return is;
}
With this, reading your format might look something like this:
istream & operator>>(istream & lhs, MyPoint & rhs) {
return lhs >> "(" >> rhs.x >> "," >> rhs.y >> ")";
}
This will do like most typical overloads and set the stream's fail bit if the pattern you've given isn't matched. As it stands now, each string in the input can be preceded by arbitrary white space (just like conversions for numbers and such).
There is technically a minor bug here: as it stands right now, this uses the global locale's definition of whitespace. To be really correct, it should probably use the definition provided in the locale associated with the input stream.
Also note that I had to change your definition of operator>> bit; in the question it looks like an overload of operator<<, with just those two characters changed to get operator>> instead.
For a quick example:
#include <iostream>
std::istream &operator>>(std::istream &is, char const *pat) {
// implementation above
}
class Point {
int x, y;
friend std::istream &operator>>(std::istream &is, Point &p) {
return is >> "(" >> p.x >>"," >> p.y >> ")";
}
friend std::ostream &operator<<(std::ostream &os, Point const &p) {
return os << "(" << p.x <<", " << p.y << ")";
}
};
int main() {
Point p;
std::cout << "Please enter a point: ";
std::cin >> p;
std::cout << "Thanks. Point: " << p << '\n';
}
Tested with VC++ 2013, VC++ 2015, and g++ 6.1 (but this isn't pushing the limits of compilers at all, so I'd expect it to work fine even with compilers so old they're horribly broken in general (e.g., gcc 2.x or VC++ 6.0).
If I have this code
struct Unit{
int coef; //coefficient
int exp; //exponent
};
class Func: private std::list<Unit>{
public:
Func();
friend std::ostream& operator<<(std::ostream &, Func);
};
How do I print it out?
I tried using the concept from here: http://www.cplusplus.com/forum/beginner/5074/
But without success:
ostream& operator<<(ostream &output, Func &pol)
{
list<Unit>::iterator i;
for( i = pol.begin(); i != pol.end(); ++i)
{
Unit test = *i;
output << test.coef << " ";
}
return output;
}
And do I initialize it correctly?
Func::Func()
{
Unit test;
test.coef = 0;
test.exp = 0;
Func::push_back(test);
}
Sorry. New to this about inheritance. Though it wasn't hard when it was about the classes I made myself.
Updated code:
struct Unit{
int coef; //coefficient
int exp; //exponent
Unit():coef(0),exp(0){}
};
class Func : public std::list<Unit>{
public:
Func();
friend std::ostream& operator<<(std::ostream &, const Func &);
};
Func::Func()
{
Unit test;
Func::push_back(test);
}
ostream& operator <<(std::ostream &output, const Func& pol)
{
for (list<Unit>::const_iterator i = pol.begin(); i != pol.end(); output << i->coef << " " << i->exp << " ", ++i);
return output;
}
It is not clear for me what do you want to do. Is is a requirement that you inherit from an STL list? I wouldn't do it.
But this at least would be a solution.
struct Unit{
int coef; //coefficient
int exp; //exponent
};
std::ostream& operator<<(std::ostream &os, Unit const& v)
{
os << v.coef << " " << v.exp << std::endl;
return os;
}
int main()
{
std::list<Unit> myList;
Unit element;
element.coef = 0;
element.exp = 0;
myList.push_back(element);
std::ostringstream os;
for (std::list<Unit>::const_iterator it = myList.begin(); it != myList.end(); ++it)
{
os << *it;
}
std::cout << os.str() << std::endl;
}
With C++11 this could be implemented much nicer, but I don't know what compiler you are using. I did not compile it so far, just hacked it down; so sorry for syntax errors.
First, regarding your printing. You can do it a number of ways, the most robust being defining free operators for each type. Such as:
struct Unit{
int coef; //coefficient
int exp; //exponent
};
std::ostream& operator <<(std::ostream& os, const Unit& unit)
{
os << unit.coef << "X^" << unit.exp;
return os;
}
The function is a little more complex. You would be better served to use the list as a member variable and provide an operator for stream insertion for that class. Such as:
#include <iostream>
#include <iterator>
#include <list>
#include <cstdlib>
struct Unit
{
int coef; //coefficient
int exp; //exponent
Unit(int coef, int exp=0)
: coef(coef), exp(exp)
{}
friend std::ostream& operator <<(std::ostream&, const Unit&);
};
std::ostream& operator <<(std::ostream& os, const Unit& unit)
{
os << unit.coef << "X^" << unit.exp;
return os;
}
class Func
{
public:
std::list<Unit> units;
friend std::ostream& operator <<(std::ostream&, const Func&);
};
std::ostream& operator <<(std::ostream& os, const Func& func)
{
std::copy(func.units.begin(), func.units.end(),
std::ostream_iterator<Unit>(os, " "));
return os;
}
int main()
{
Func func;
func.units.push_back(Unit(3, 2));
func.units.push_back(Unit(2, 1));
func.units.push_back(Unit(1, 0));
std::cout << func << endl;
return EXIT_SUCCESS;
}
Output
3X^2 2X^1 1X^0
Note: I did NOT properly hide members, provide accessors, etc. That I leave to you, but the general idea on how to provide output-stream operators should be obvious. You could significantly further enhance the output operator for a `Unit by:
Not printing exponents of 1
Only printing the coefficient for exponents of 0 (no X),
Not printing a 1 coefficient of any term with an exponent greater than 0
Not printing anything for terms with 0 coefficients.
These tasks I leave to you.