Problem with functor, maybe I need operator== for my struct?

F

Fencer

Hello, I am very rusty in C++ and I'm having some problems: I have a
std::set<SomeClass> and I need to look through the set to find if any of
the instances of SomeClass that it contains has a particular value for
one of its data members. I know I could simply iterate through the set
myself and check every SomeClass instance if any of them is a match, but
I tried to do it using functors instead.
The following simplified test program does not build, and it seems to be
that operator== is missing for the struct s1. Could you gurus help me
explain why my test program does not build and how I should fix it?

#include <algorithm>
#include <functional>
#include <set>

using namespace std;

struct s1
{
s1(int u, int v) : u(u), v(v) {}

int u, v;
};

struct OnV : public unary_function<s1, bool>
{
explicit OnV(int v) : v(v) {}

bool operator()(s1 const& inst) const
{
return v == inst.v;
}

int v;
};

int main()
{
set<s1> a_set;

find(a_set.begin(), a_set.end(), OnV(4711));
}

$ g++ -Wall -Wextra -std=c++98 -pedantic functor.cpp -o functor.exe
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h: In
function ‘_InputIterator std::__find(_InputIterator, _InputIterator,
const _Tp&, std::input_iterator_tag) [with _InputIterator =
std::_Rb_tree_const_iterator<s1>, _Tp = OnV]’:
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h:3814:
instantiated from ‘_IIter std::find(_IIter, _IIter, const _Tp&) [with
_IIter = std::_Rb_tree_const_iterator<s1>, _Tp = OnV]’
functor.cpp:30: instantiated from here
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h:151:
error: no match for ‘operator==’ in
‘__first.std::_Rb_tree_const_iterator<_Tp>::eek:perator* [with _Tp = s1]()
== __val’

Thank you for reading and thanks for any help! Even though I could use
the alternative solution I mentioned above that does not involve
functors, I wanted to know what I did wrong with my functor and
hopefully learn something from your replies.

- Fencer
 
S

Saeed Amrollahi

Hello, I am very rusty in C++ and I'm having some problems: I have a
std::set<SomeClass> and I need to look through the set to find if any of
the instances of SomeClass that it contains has a particular value for
one of its data members. I know I could simply iterate through the set
myself and check every SomeClass instance if any of them is a match, but
I tried to do it using functors instead.
The following simplified test program does not build, and it seems to be
that operator== is missing for the struct s1. Could you gurus help me
explain why my test program does not build and how I should fix it?

#include <algorithm>
#include <functional>
#include <set>

using namespace std;

struct s1
{
    s1(int u, int v) : u(u), v(v) {}

    int u, v;

};

struct OnV : public unary_function<s1, bool>
{
    explicit OnV(int v) : v(v) {}

    bool operator()(s1 const& inst) const
    {
       return v == inst.v;
    }

    int v;

};

int main()
{
    set<s1> a_set;

    find(a_set.begin(), a_set.end(), OnV(4711));

}

$ g++ -Wall -Wextra -std=c++98 -pedantic functor.cpp -o functor.exe
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h: In
function ‘_InputIterator std::__find(_InputIterator, _InputIterator,
const _Tp&, std::input_iterator_tag) [with _InputIterator =
std::_Rb_tree_const_iterator<s1>, _Tp = OnV]’:
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h:3814:
instantiated from ‘_IIter std::find(_IIter, _IIter, const _Tp&) [with
_IIter = std::_Rb_tree_const_iterator<s1>, _Tp = OnV]’
functor.cpp:30:   instantiated from here
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h:151:
error: no match for ‘operator==’ in
‘__first.std::_Rb_tree_const_iterator<_Tp>::eek:perator* [with _Tp = s1]()
== __val’

Thank you for reading and thanks for any help! Even though I could use
the alternative solution I mentioned above that does not involve
functors, I wanted to know what I did wrong with my functor and
hopefully learn something from your replies.

- Fencer

Hi

You need to special function objects called predicate
and find_if generic function:

struct Pair
{
Pair(int u, int v) : u(u), v(v) {}
int u, v;
};

// Just for illustration: Somehow inkorect and incomplt
// Set relies on a comparison operation (by default <)
bool operator<(const Pair& p1, const Pair& p2)
{
return (p1.u < p2.u && p1.v < p2.v) ? true : false;
}

struct CheckV { // predicate
explicit CheckV(int v) : v(v) {}
bool operator()(Pair const& inst) const
{
return v == inst.v;
}
int v;
};

struct CheckU { // predicate
explicit CheckU(int u) : u(u) {}
bool operator()(Pair const& inst) const
{
return u == inst.u;
}
int u;
};

#include <set>
#include <algorithm>
#include <iostream>

int main()
{
using namespace std;
set<Pair> MySet;
MySet.insert(Pair(0, 1));
MySet.insert(Pair(1, 2));
MySet.insert(Pair(2, 4711));

set<Pair>::const_iterator cit =
find_if(MySet.begin(), MySet.end(), CheckV(4711));
if (cit != MySet.end())
cout << "(" << cit->u << ", " << cit->v << ")\n";

return 0;
}

HTH,
-- Saeed Amrollahi
 
S

Saeed Amrollahi

On Jul 25, 2:25 pm, Fencer<[email protected]>
wrote: [snip]
// Just for illustration: Somehow inkorect and incomplt
// Set relies on a comparison operation (by default<)
bool operator<(const Pair&  p1, const Pair&  p2)
{
   return (p1.u<  p2.u&&  p1.v<  p2.v) ? true : false;
}

perhaps you meant:

        return p1.u < p2.u || (p1.u == p2.u && p1.v < p2.v);

"? true : false" is superfluous BTW.

[snip]

/Leigh

May be. I just want to say for using set and its insert operation
we should have operator function <.
About your implementation, I guess it depends to
exact meaning of pair. pair as a point
is different from pair as an numbers interval.

Cheers,
-- Saeed Amrollahi
for example
 
S

Saeed Amrollahi

On 25/07/2011 13:14, Saeed Amrollahi wrote:
On Jul 25, 2:25 pm, Fencer<[email protected]>
wrote:
[snip]
// Just for illustration: Somehow inkorect and incomplt
// Set relies on a comparison operation (by default<)
bool operator<(const Pair&    p1, const Pair&    p2)
{
    return (p1.u<    p2.u&&    p1.v<    p2.v) ? true : false;
}
perhaps you meant:
         return p1.u<  p2.u || (p1.u == p2.u&&  p1.v<  p2.v);
"? true : false" is superfluous BTW.
[snip]
/Leigh
May be. I just want to say for using set and its insert operation
we should have operator function<.
About your implementation, I guess it depends to
exact meaning of pair. pair as a point
is different from pair as an numbers interval.

Your version doesn't work; mine does.  In your version (1, 2) is
equivalent to (1, 3) and (1, 2) is equivalent to (2, 1); this is plainly
wrong.  Hint: (a == b) is the same as !(a < b) && !(b < a).

/Leigh

Yes. You are right.
I really didn't think a lot about my implementation
as I mentioned in the comment.

Regards,
-- Saeed Amrollahi
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top