Vector of structs - not seeing my definition for operator== - c++

I have a class called Something that has two things: a string, and a vector of instructions. In that class, I want to define operator==. However, I get an error when I try to compile:
error: no match for ‘operator==’ in ‘* __first1 == * __first2’
This happened at the line where I am comparing the two vectors in Something using == (since vector has that conveniently defined, I would like to use it).
instruction is as follows:
struct instruction
{
int instr;
int line;
bool operator==(const instruction& rhs)
{
return (instr == rhs.instr) && (line == rhs.line);
}
};
I've searched for a solution to no avail. It seems that vector from the STL is not seeing the operator== I have defined for my struct when it's comparing these elements.

You haven't shown the code that's actually failing, but most likely is a scenario such as this:
int main()
{
vector <instruction> ins;
vector <instruction>::const_iterator itA = /*...*/, itB = /*...*/;
bool b = (*itA == *itB);
}
In this case, the problem is the fact that operator== is not const. Change the declaration as follows:
bool operator==(const instruction& rhs) const
^^^^^^^

Try to add qualifier const to the operator ==.
Also you did not show how the vector is declared and used.

You probably want to make the operator=() method itself const. You do that by adding 'const':
struct instruction
{
int instr;
int line;
bool operator==(const instruction& rhs) const // add const keyword here
{
return (instr == rhs.instr) && (line == rhs.line);
}
};

Related

== operator overloading with struct

I'm trying to define an == operator within a struct, like this:
struct names {
string fname;
string lname;
bool operator==(names a, names b) {
return (a.fname == b.lname);
}
};
However, the compiler says:
..\src\trash.cpp:10:33: error: 'bool names::operator==(names, names)' must take exactly one argument
Why is this?
If you overload a binary operator as a member function, then it should only take one argument. The first operand is the object the operator is called on (i.e. *this); the second operand is the single function argument.
struct names {
//...
// better to pass by reference;
// make the function 'const' so it can be used on constant objects
bool operator==(names const & rhs) const {
return this->fname == rhs.lname;
}
};
Alternatively, you can overload it as a non-member function, with two arguments:
bool operator==(names const & lhs, names const & rhs) {
return lhs.fname == rhs.lname;
}
If this needed access to private members (which isn't the case in this example), then it would have to be a friend. You can define friends inside the class definition; in which case the code would look exactly the same as your example, only with friend in front of the function declaration.
(Of course, this isn't a sensible definition of equality since it's not symmetric. Many algorithms will break if you can have a == b but not b==a, as you can with this definition. lhs.fname == rhs.fname && lhs.lname == rhs.lname would make more sense.)
operator== is meant to compare two objects for equality. You have it appearing to compare the first and last names for different objects, presumably to catch duets like George Lazenby and Emma George.
I'd make it a member function of the class and use this for one of the objects:
bool operator== (const names &rhs) const {
return (this->fname == rhs.fname) && (this->lname == rhs.lname);
}
Do:
As member function:
struct names {
string fname;
string lname;
bool operator==(const names& rhs) const { /* Your code */ }
};
or as free function:
bool operator==(const names& lhs, const names& rhs) const { /* Your code */ }

How to create a set with my customized comparison in c++

Could someone explain me what is going on in this example here?
They declare the following:
bool fncomp (int lhs, int rhs) {return lhs<rhs;}
And then use as:
bool(*fn_pt)(int,int) = fncomp;
std::set<int,bool(*)(int,int)> sixth (fn_pt)
While the example for the sort method in algorithm library here
can do like this:
bool myfunction (int i,int j) { return (i<j); }
std::sort (myvector.begin()+4, myvector.end(), myfunction);
I also didn't understand the following:
struct classcomp {
bool operator() (const int& lhs, const int& rhs) const
{return lhs<rhs;}
};
this keyword operator (not being followed by an operator as in a op. overload)... what is the meaning of it? Any operator applied there will have that behavior? And this const modifier... what is the effect caused by it?
I was trying to make a set of C-style string as follows:
typedef struct
{
char grid[7];
} wrap;
bool compare(wrap w1, wrap w2)
{
return strcmp(w1.grid, w2.grid) == -1;
}
set <wrap, compare> myset;
I thought I could create a set defining my sorting function in a similar as when I call sort from algorithm library... once it didn't compile I went to the documentation and saw this syntax that got me confused... Do I need to declare a pointer to a function as in the first example i pasted here?
struct classcomp {
bool operator() (const int& lhs, const int& rhs) const
{return lhs<rhs;}
};
Defines a functor by overloading the function call operator. To use a function you can do:
int main() {
std::set <wrap, bool (*)(wrap,wrap)> myset(compare);
return 0;
}
Another alternative is to define the operator as a part of the wrap class:
struct wrap {
char grid[7];
bool operator<(const wrap& rhs) const {
return strcmp(this->grid, rhs.grid) == -1;
}
};
int main() {
wrap a;
std::set <wrap> myset;
myset.insert(a);
return 0;
}
You're almost there... here's a "fixed" version of your code (see it run here at ideone.com):
#include <iostream>
#include <set>
#include <cstring>
using namespace std;
typedef struct
{
char grid[7];
} wrap;
bool compare(wrap w1, wrap w2) // more efficient: ...(const wrap& e1, const wrap# w2)
{
return strcmp(w1.grid, w2.grid) < 0;
}
set <wrap, bool(*)(wrap, wrap)> myset(compare);
int main() {
wrap w1 { "abcdef" };
wrap w2 { "ABCDEF" };
myset.insert(w1);
myset.insert(w2);
std::cout << myset.begin()->grid[0] << '\n';
}
"explain [to] me what is going on in this example"
Well, the crucial line is...
std::set<wrap, bool(*)(wrap, wrap)> myset(compare);
...which uses the second template parameter to specify the type of function that will perform comparisons, then uses the constructor argument to specify the function. The set object will store a pointer to the function, and invoke it when it needs to compare elements.
"the example for the sort method in algorithm library..."
std::sort in algorithm is great for e.g. vectors, which aren't automatically sorted as elements are inserted but can be sorted at any time. std::set though needs to maintain sorted order constantly, as the logic for inserting new elements, finding and erasing existing ones etc. all assumes the existing elements are always sorted. Consequently, you can't apply std::sort() to an existing std::set.
"this keyword operator (not being followed by an operator as in a op. overload)... what is the meaning of it? Any operator applied there will have that behavior? And this const modifier... what is the effect caused by it?
operator()(...) can be invoked on the object using the same notation used to call a function, e.g.:
classcomp my_classcomp;
if (my_classcomp(my_int1, my_int_2))
std::cout << "<\n";
As you can see, my_classcomp is "called" as if it were a function. The const modifier means that the code above works even if my_classcomp is defined as a const classcomp, because the comparison function does not need to modify any member variables of the classcomp object (if there were any data members).
You almost answered your question:
bool compare(wrap w1, wrap w2)
{
return strcmp(w1.grid, w2.grid) == -1;
}
struct wrap_comparer
{
bool operator()(const wrap& _Left, const wrap& _Right) const
{
return strcmp(_Left.grid, _Right.grid) == -1;
}
};
// declares pointer to function
bool(*fn_pt)(wrap,wrap) = compare;
// uses constructor with function pointer argument
std::set<wrap,bool(*)(wrap,wrap)> new_set(fn_pt);
// uses the function directly
std::set<wrap,bool(*)(wrap,wrap)> new_set2(compare);
// uses comparer
std::set<wrap, wrap_comparer> new_set3;
std::sort can use either a function pointer or a function object (http://www.cplusplus.com/reference/algorithm/sort/), as well as std::set constructor.
const modifier after function signature means that function can't modify object state and so can be called on a const object.

Polymorphism,STL,find and operator==

I ran into a problem.
I have a class A,and a class that inherits from A,lets call it class B.
I have virtual functions.
I want to compare A and B to another class C by operator==.
If i want to have a list of A's,lets say in stl list,
I must use a pointer to A,so it will look like:
list<*A> list;
and also i have: C something
but now,i cant use the function:find(list.begin(),list.end(),something)
because i cant use operator == for pointers(*).
I found a solution but i dont think its the best,so my question is-can i do it better?
iter=list.begin();
for(iter;iter!=list.end();++iter)
{
if((*iter).operator==(something)
return ...
}
Thank you.
You could use find_if, which lets you provide a function to check for equal values.
auto check_something =
[&something](const list<*A>::iterator& iter){return *iter == something; };
find_if(list.begin(),list.end(),check_something)
You can use
if(**iter == something)
if you want to dereference the pointer.
In C++1x, there is also
for(auto ptr : list)
if(*ptr == something)
Nothing says you can't make a global non-member operator == that operates on pointers or combinations of pointers and objects. If you have many types you could template the combination of pointer vs object equality for any type.
Edit to add this tip: Put the comparison in a namespace with your objects and then argument dependent lookup will find it without putting a global T* == T in scope that catches everything:
namespace equals {
struct A {
A(int x) :x(x) { }
bool operator == (const A &other) const {
return other.x == x;
}
int x;
};
template <typename T>
bool operator == (const T *lhs, const T &rhs) {
return *lhs == rhs;
}
template <typename T>
bool operator == (const T &lhs, const T *rhs) {
return lhs == *rhs;
}
}
Now you can do things like:
equals::A b(1), c(1);
if (b == &c) std::cerr << "good!" << std::endl;
You might have a look at boost::indirect_iterator which is designed for just this purpose.
find(
boost::make_indirect_iterator( list.begin() ),
boost::make_indirect_iterator( list.end() ),
something );

C++: vector containers and <algorithm> std::find

I created a struct that contains information about variables, namely their name and number
struct var{
string name;
int value;
};
Now, I want to use iterators to update it, using the following function:
void updateVariable(vector<Variable>& vars,Variable& newVar){
vector<Variable>::iterator it = find(vars.begin(), vars.end(), newVar);
if(it == vars.end()){
vars.push_back(newVar);
}
else{
*it = newVar;
}
}
Just to be sure, the error I'm getting is at the line with the call to find(). Any ideas why I'm getting the error? Here is the error:
/usr/include/c++/4.6/bits/stl_algo.h:162:4: error: no match for ‘operator==’ in ‘__first.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = Variable*, _Container = std::vector<Variable>, __gnu_cxx::__normal_iterator<_Iterator, _Container>::reference = Variable&]() == __val’
Update:
Thank you guys for all the quick help, and the clear answers!
You haven't defined operator == for your var struct. The find() algorithm by default will use operator == to compare the value you provide with the values in the specified range, and return the iterator to the first element which compares equal.
To fix this, just overload operator == for your class. One way to do that is this:
struct var
{
string name;
int value;
};
bool operator == (var const& v1, var const& v2)
{
return (v1.name == v2.name) && (v1.value == v2.value);
}
Make sure you define operator == in the same namespace as your var structure, otherwise ADL (Argument Dependent Lookup) will fail and you will likely get a compiler error.
If you are working with C++11 and you do not want to bother defining an overloaded version of operator ==, you can even use find_if() and pass a lambda as the last argument:
find_if(vars.begin(), vars.end(), [&] (var const& v) {
return (v.name == newVar.name) && (v.value == newVar.value);
});
As GManNickG correctly points out, when you need to compare several members, using std::tie and the overloaded operator == for std::tuple may save you some typing:
auto const tieMembers = [] (const var&) {
return std::tie(v.name, v.value, ...);
};
The above lambda can then be used this way when comparing values v1 and v2 of type var:
return (tieMembers(v1) == tieMembers(v2));
You need to define an overload of operator== for var. This should work.
bool operator==(const var& a, const var& b){
return (a.name == b.name) && (a.value == b.value);
}

operator== overloading considering non-static member function

I have defined a class like this
using namespace std;
class foo {
public:
typedef std::pair< int, int > index;
bool operator == ( const index &l, const index &r )
{
return (l.first == r.first && l.second == r.second);
}
void bar()
{
index i1;
i1.first = 10;
i1.second = 20;
index i2;
i2.first = 10;
i2.second = 200;
if (i1 == i2)
cout << "equal\n";
}
};
However I get this error in windows
error C2804: binary 'operator ==' has too many parameters
and this error in linux
operator==(const std::pair<int, int>&, const std::pair<int, int>&)’ must take exactly one argument
I found this topic overloading operator== complaining of 'must take exactly one argument' and seems to be a problem with static and non-static functions in a class. However I don't know how to apply this
For example, this is not correct
bool operator == ( const index &r )
{
return (this->first == r.first && this->second == r.second);
}
How can I fix that?
The operator== can be implemented in two ways:
As member function: in this case, the function takes one argument and is invoked on the left operand which is passed as this pointer implicitly to the function.
As non-member function, in which case, the function takes two arguments, left and right operands.
Since you're implementing operator== for std::pair, you cannot implement it as member function (of std::pair). The option you're left with is non-member function.
So implement it outside the class as:
bool operator==(std::pair<int,int> const & l, std::pair<int,int> const & r)
{
return (l.first == r.first && l.second == r.second);
}
But then you don't really need to implement it yourself unless you want to implement it differently. The Standard Library has already provided a generic version of operator== for std::pair which lexicographically compares the values in the pair, like I did above, i.e compare first with first and second with second. If you need to compare them differently, only then provide your own specific definition (non-template version).
The above mentioned points are worth noting as to how to implement operator== when you need it for your defined types.
You need to move operator== out of class foo:
bool operator == ( const foo::index &l, const foo::index &r )
{
return (l.first == r.second && l.second == r.second);
}
class foo {
public:
typedef std::pair< int, int > index;
void bar()
{
index i1;
i1.first = 10;
i1.second = 20;
index i2;
i2.first = 10;
i2.second = 200;
if (i1 == i2)
cout << "equal\n";
}
};
Also note, std::pair has overload operator== already, see: link, you might reconsider if necessary to write your own again.
If you overload the == operator inside a class, it should only take a single parameter so that comparison can be done between the current object and the argument.
You can move that operator out of the class, that way you can take 2 operands. Indeed there is no point of keeping it within the class at this point, since you are only comparing member variables and not the class itself.
Indeed I wont be surprised if pair already defines the operator you write.
Edit : Yup It looks like pair already implements this
Two pair objects are compared equal if the first elements in both objects compare equal to each other and both second elements also compare equal to each other - they all have to match.
p.s. I think you meant
return (l.first == r.first && l.second == r.second);
^^^^^^