error C2678 in using template - c++

I'm defining a priority queue and use it on a self-defined struct but I get this error and I don't know how to fix it.
This is my error:
error C2678: binary '<' : no operator found which takes a left-hand operand
of type 'const Location' (or there is no acceptable conversion)
my struct Location
struct Location
{
int x, y, value;
Location(int a, int b);
bool operator == (const Location& other);
bool operator < (const Location& other);
};
Location:: Location(int a, int b) {
x = a;
y = b;
value = 0;
}
bool Location:: operator == (const Location& other) {
return (x == other.x && y == other.y);
}
bool Location:: operator < (const Location& other) {
return value > other.value;
}
Here's my priority queue
template<typename T>
struct my_priority_queue {
priority_queue<T, vector<T>, greater<T>> elements;
bool empty()
{
return elements.empty();
}
void push(T item)
{
elements.emplace(item);
}
T pop()
{
T best = elements.top();
elements.pop();
return best;
}
};
The main function
int main() {
Location a(0, 0);
Location b(1, 2);
Location c(3, 0);
my_priority_queue<Location> my_pq;
my_pq.push(a);
}

It's as it says.
Your operator cannot take a const Location on the LHS, because it is not a const function.
bool operator == (const Location& other) const;
bool operator < (const Location& other) const;
// ^^^^^^

Related

Cant get my sorting rule right for std::map

I have trying to use a class as a key in an std::map. I have read documentations and I know I have to type some sort of sorting rule because my std::map is a binary search tree. The problem arise because the class key have another classes in it. Can someone get me some advice how to build the operators?
MasterRenderer file
std::map<TexturedModel, std::vector<Entity>> entites;
void MasterRenderer::processEntity(Entity entity)
{
TexturedModel model = entity.getModel();
auto search = entites.find(model);
if (search != entites.end()) {
//found
entites[model].emplace_back(entity);
}
else {
//not found
entites[model].emplace_back(entity);
}
std::cout << entites[model].size() << std::endl;
}
TexturedModel.h
TexturedModel(RawModel model, ModelTextures
texture)
:m_model(model), m_texture(texture) {
};
friend bool operator<(const TexturedModel& m,
const
TexturedModel& m2) {
return m.m_model < m2.m_model || m.m_model ==
m2.m_model && m.m_texture < m2.m_texture;
}
private:
RawModel m_model;
ModelTextures m_texture;
};
Rawmodel.h
unsigned int VaoID;
unsigned int Vertecies;
RawModel(unsigned int vaoID, unsigned int
vertecies)
:VaoID(vaoID), Vertecies(vertecies) {};
friend bool operator <(const RawModel& rhs, const
RawModel& rhs2)
{
return rhs.get() < rhs2.get();
}
friend bool operator ==(const RawModel& rhs, const
RawModel& rhs2)
{
return rhs.get() == rhs2.get();
}
const RawModel* get() const {
return this;
}
ModelTextures.h
ModelTextures(unsigned int ID)
:textureID(ID) {};
friend bool operator<(const ModelTextures& rhs,
const ModelTextures& rhs2)
{
return rhs.get() < rhs2.get();
}
const ModelTextures* get() const{
return this;
}
private:
unsigned int textureID;
float shineDamper = 1.0f;
float reflectivity = 0.0f;
};
friend bool operator<(const ModelTextures& rhs,
const ModelTextures& rhs2)
{
return rhs.get() < rhs2.get();
}
const ModelTextures* get() const{
return this;
}
this orders by address of the object, not content. That violates the requirements of std::map.
friend auto as_tie(const ModelTexture& m) {
return std::tie(m.textureID, m.shineDamper, m.reflexivity);
}
friend bool operator<(const ModelTextures& rhs,
const ModelTextures& rhs2)
{
return as_tie(rhs) < as_tie(lhs);
}
repeat this pattern for TexturedModel and RawModel.
If you are stuck in c++11 you have to manually write the return type of as_tie or use decltype.
friend auto as_tie(const ModelTexture& m)
-> decltype(std::tie(m.textureID, m.shineDamper, m.reflexivity))
{
return std::tie(m.textureID, m.shineDamper, m.reflexivity);
}

std::find with two different types

I am trying to use std::find with two different types but providing the necessary boolean operators.
class FooDetails
{
public:
FooDetails(int size = 5)
: m_size(size) { /* empty */ }
bool operator<(const FooDetails& other) const { return m_size < other.m_size; }
bool operator==(const FooDetails& other) const { return m_size == other.m_size; }
private:
int m_size;
};
class Foo
{
public:
Foo(int size)
: m_details(size) { /* empty */}
bool operator==(const Foo& other) const { return m_details == other.m_details; }
bool operator==(const FooDetails& other) const {return m_details == other; }
bool operator<(const Foo& other) const { return m_details < other.m_details; }
bool operator<(const FooDetails& other) const { return m_details < other; }
FooDetails m_details;
};
bool operator==(const FooDetails& lhs, const Foo& rhs) { return lhs == rhs.m_details; }
bool operator==(const Foo& lhs, const FooDetails& rhs) {return lhs.m_details == rhs; }
bool operator<(const FooDetails& lhs, const Foo& rhs) { return lhs < rhs.m_details; }
bool operator<(const Foo& lhs, const FooDetails& rhs) { return lhs.m_details < rhs; }
int main() {
std::vector<Foo> haystack = { FooDetails(5), FooDetails(6), FooDetails(7) };
FooDetails needle(6);
std::find(haystack.begin(), haystack.end(), needle);
return 0;
}
Since std::find uses operator== I would expect this to work, since all necessary functions are provided. However this does not compile. Why is that and how do I fix it?
I know I could use std::find_if, but I assume that's a bit slower and even if it's not I'd like to know why std::find doesn't work.
I've changed your code to this:
#include <algorithm>
class FooDetails
{
public:
FooDetails(int size = 5)
: m_size(size) { /* empty */ }
bool operator<(const FooDetails& other) const { return m_size < other.m_size; }
bool operator==(const FooDetails& other) const { return m_size == other.m_size; }
private:
int m_size;
};
class Foo
{
public:
Foo(int size)
: m_details(size) { /* empty */}
FooDetails m_details;
};
bool operator==(const FooDetails& lhs, const Foo& rhs) { return lhs == rhs.m_details; }
bool operator==(const Foo& lhs, const FooDetails& rhs) {return lhs.m_details == rhs; }
bool operator<(const FooDetails& lhs, const Foo& rhs) { return lhs < rhs.m_details; }
bool operator<(const Foo& lhs, const FooDetails& rhs) { return lhs.m_details < rhs; }
int main() {
std::vector<Foo> haystack = { Foo(5), Foo(6), Foo(7) };
FooDetails needle(6);
std::find(haystack.begin(), haystack.end(), needle);
return 0;
}
And it successfully compiles. Your original version contains two errors:
You try to create std::vector<Foo> initialising it with std::initialization_list<FooDetails>.
You have provided too many comparison operators: both free versions and members of the Foo struct. So during lookup compiler complains that it doesn't know which one of them to choose. You should leave only one of them.
You have no such constructor in Foo class which constructs it from FooDetails. You need to define the following and your code will work:
Foo(const FooDetails& d) : m_details(d) {}

I want to check if a class instance is already stored in a std::vector

I hope the title describes my problem completely.
Running the code I get an error:
error C2678: binary '==':no operator found which takes a left-hand operand of tpye 'A' (or there is no acceptable conversion)"
Where is the mistake and how can I fix the problem???
class A
{
private: //Dummy Values
int x;
int y;
}
class B
{
private:
vector <A> dataHandler;
public:
bool isElement(A element);
//Should return true if element exists in dataHandler
}
bool B::isElement(A element)
{
int length = dataHandler.size();
for(int i = 0; i<length; i++)
{
if(dataHandler[i] == element) //Check if element is in dataHandler
return true;
}
return false;
}
Within isElement you have
if(dataHandler[i] == element)
This is attempting to compare two A instances using operator==, but your A class doesn't implement any such operator overload. You probably want to implement one similar to this
class A
{
private: //Dummy Values
int x;
int y;
public:
bool operator==(A const& other) const
{
return x == other.x && y == other.y;
}
};
Also, isElement can be rewritten using std::find instead of a for loop
bool B::isElement(A const& element) const
{
return std::find(dataHandler.begin(), dataHandler.end(), element) != dataHandler.end();
}
Compiler tells you everything. Define operator== for class A. Update class A to something like this:
class A
{
private: //Dummy Values
int x;
int y;
public:
bool operator==(A const& rhs) const
{
return x == rhs.x && y == rhs.y;
}
};
you have to write your own == operator for class A, something like
bool operator==(const A &rhs) const
{
return this->x == rhs.x && this->y == rhs.y;
}
otherwise there's no way to know how to compare A objects.
You will have to implement the operator==.
Example of operator== (inline non-member function):
inline bool operator== (const A& left, const A& right){
return left.getX() == right.getX() && left.getY() == right.getY();
}

Understanding the Next_Permutation Function in C++ for a Vector of Objects

I would like help figuring out how to use the next_permutation function on a vector of objects. I've read about people using the comp parameter, but I don't understand it. I thought the overloaded operators would fix things, but I'm still getting thrown errors. Please help me with my syntax and/or explain (with examples) the comp parameter of the next_permutation function! Thanks!
In my main file:
vector<Point> source;
//fill vector with Points, say 4 of them (1,2)(2,3)(3,4)(4,5)
next_permutation(source.begin(), source.end()); // at run I get error "Invalid operands to binary expression ('Const Point' and 'Const Point)"
My simple Point class:
class Point {
private:
double xval, yval;
public:
Point(int x = 0, int y = 0) {
xval = x;
yval = y;
}
int x() { return xval; }
int y() { return yval; }
friend bool operator<(Point& lhs, Point& rhs){
return lhs.x() < rhs.x() || (lhs.x()==rhs.x() && lhs.y()<rhs.y()) ;
}
friend bool operator==(Point& lhs, Point& rhs) {
return lhs.x()==rhs.x() && lhs.y()==rhs.y();
}
};
EDIT: This also throws the same error:
int x() const { return xval; }
int y() const { return yval; }
friend bool operator<(const Point& lhs, const Point& rhs){
return lhs.x() < rhs.x() || (lhs.x()==rhs.x() && lhs.y()<rhs.y()) ;
}
friend bool operator==(const Point& lhs, const Point& rhs) {
return lhs.x()==rhs.x() && lhs.y()==rhs.y();
}
This also throws the same error:
int x() const { return xval; }
int y() const { return yval; }
bool operator<(const Point& lhs){
return lhs.x() < x() || (lhs.x()==x() && lhs.y()<y()) ;
}
bool operator==(const Point& lhs) {
return lhs.x()==x() && lhs.y()==y();
}
Use const references and const getter functions.
int x() const { return xval; }
int y() const { return yval; }
friend bool operator<(const Point& lhs, const Point& rhs){
return lhs.x() < rhs.x() || (lhs.x()==rhs.x() && lhs.y()<rhs.y()) ;
}
friend bool operator==(const Point& lhs, const Point& rhs) {
return lhs.x()==rhs.x() && lhs.y()==rhs.y();
}
http://liveworkspace.org/code/4Drerr$0
Getter functions should be const member function, also any reason you convert from double to int?
Try:
double x() const { return xval; }
double y() const { return yval; }

c++ How to search if struct element in vector is equal?

A class named SparseMatrix has a vector of Nodes struct. I want to overload the += operator so that if the i and j members of a Node instance are the same then the value of that node will be added to This. How can i accomplish this using methods from the algorithm library?
I tried using find_if to pass to a function but it act only on one iterator:
class SparseMatrix
{
public:
SparseMatrix(int numRow,int numCol, std::vector<double> fill);
SparseMatrix(int numRow,int numCol);
SparseMatrix();
// assignment operations
bool operator==(const SparseMatrix &other) const;
bool operator!=(const SparseMatrix &other) const;
void operator-() const;
// compound operations
SparseMatrix& operator+=(const SparseMatrix &other);
SparseMatrix& operator*=(const SparseMatrix &other);
// binary operations
const SparseMatrix operator+(const SparseMatrix &other) const;
const SparseMatrix operator*(const SparseMatrix &other) const;
friend std::ostream& operator<<(std::ostream& output, const SparseMatrix sparseMatrix);
bool trace(double& result) const;
bool det(double& result) const;
SparseMatrix transpose();
~SparseMatrix(){};
protected:
vector<Node> _matrix;
int _numCol, _numRow;
};
typedef struct Node {
int i;
int j;
double value;
static bool samePosition(const Node& other)
{
return ((i == other.i) && (j == other.j));
}
} Node;
SparseMatrix& SparseMatrix::operator+=(const SparseMatrix &other)
{
vector<Node>::iterator itThis;
for (vector<Node>::iterator itOther = other._matrix.begin(); itOther != other._matrix.end(); ++itOther)
{
// find if already exists a value in the same matrix position
itThis = find_if(_matrix.begin(), _matrix.end(), Node::samePosition);
// if exists add value to position, else instantiate new Node with value & position
}
return *this;
}
Basically, I want Node::samePosition() to pass two parameters - the current iterator passed by find_if and itOther so it can check if they are equal.
EDIT: I have separated the samePosition function and now want to pass to it two parameters using find_if:
typedef struct Node {
int i;
int j;
double value;
} Node;
static bool SparseMatrix::samePosition(const Node& first, const Node& other)
{
return ((first.i == other.i) && (first.j == other.j));
}
SparseMatrix& SparseMatrix::operator+=(const SparseMatrix &other)
{
vector<Node>::iterator itThis;
for (vector<Node>::iterator itOther = other._matrix.begin(); itOther != other._matrix.end(); ++itOther)
{
itThis = find_if(_matrix.begin(), _matrix.end(), SparseMatrix::samePosition("call what here?",itOther));
}
return *this;
}
You are trying to use
static bool SparseMatrix::samePosition(const Node& first, const Node& other)
{
return ((first.i == other.i) && (first.j == other.j));
}
which is a standalone function. All its data has to be supplied by the caller, but find_if knows nothing about the Node you want to compare against the entire list.
Instead you should use a functor, which is an object that can hold some data, and also implements operator()() so that it can be called like a function.
struct position_finder
{
const Node needle;
position_finder( const Node& sought ) : needle(sought) {}
bool operator()( const Node& haystack ) const
{
return ((needle.i == haystack.i) && (needle.j == haystack.j));
// or return samePosition(needle, haystack)
}
};
and then you pass the sought Node when constructing the functor, so it gets stored for later use:
itThis = find_if(_matrix.begin(), _matrix.end(), position_finder(*itOther));
C++11 makes this all a whole lot easier, since a lambda will cause the compiler to generate that struct for you:
itThis = find_if(_matrix.begin(), _matrix.end(), [itOther](Node& arg){ return ((itOther->i == arg.i) && (itOther->j == arg.j)); });