Reputation: 187
So I'm working on a project and I have to use the set library on class objects. Those objects have many attributes, ID being one of them.
What I wanted to do was search for an object inside a "set" by its ID. The problem is set only has find and I don't know how to search for an ID this way since I'd have to use find(class object) and not find(int). I tried messing with class operators to read it as an object but couldn't find a way.
Also, I thought about algorithm::find_if, but that would just check every element from beggining to end instead of using the set "tree" search functions, right?
Thanks in advance.
Upvotes: 0
Views: 288
Reputation: 3101
You need to create a constructor for your class that takes int
as its only argument. Doing so allows implicit conversion from int
to your class, making it possible to call std::set::find(int)
, as requested.
For example:
#include <iostream>
#include <set>
class Foo {
public:
/* Normal constructor */
Foo(const char * s, int i) : str(s),id(i) {}
/* Special constructor for implicit conversion */
Foo(int i) : str(0),id(i) {}
/* Make Foo usable with std::set */
bool operator<(const Foo& f) const { return f.id<id; }
/* Make Foo printable */
friend std::ostream& operator<<(std::ostream& o, const Foo& f);
private:
const char * str;
int id;
};
std::ostream& operator<<(std::ostream& o, const Foo& f) {
return o << "(" << f.str << " " << f.id << ")";
}
typedef std::set<Foo> FooSet;
int main(void) {
FooSet s;
s.insert(Foo("test",1));
s.insert(Foo("asdf",7));
s.insert(Foo("spam",3));
for (int i=0; i<10; ++i) {
/* Note that searching is done via FooSet::find(int id) */
FooSet::const_iterator f = s.find(i);
std::cout << "Searching for id " << i << ": ";
if (f==s.end())
std::cout << "absent";
else
std::cout << "present " << *f;
std::cout << std::endl;
}
return 0;
}
This yields:
Searching for id 0: absent
Searching for id 1: present (test 1)
Searching for id 2: absent
Searching for id 3: present (spam 3)
Searching for id 4: absent
Searching for id 5: absent
Searching for id 6: absent
Searching for id 7: present (asdf 7)
Searching for id 8: absent
Searching for id 9: absent
Upvotes: 0
Reputation: 264411
If your class is already compatable with a set then you have defined the operator< or have provided a specific comparitor for comparing elements using a strict weak ordering.
struct X
{
X(int pid): id(pid) {}
int id;
bool operator<(X const& rhs) { return this->id < rhs.id;}
};
std::set<X> data;
std::set<X>::const_iterator find = data.find(X(12));
if (find != data.end())
{
// You found the item
}
This has the drawbacks in that you need to define X in a way that you can easily create temporary objects with a specific ID and the operator< (or the comparitor) is just a strict weak ordering of the ID.
An alternative is to use std::find_if() with a custom comparitor:
struct TestXID
{
TestXID(int testId): tid(testId) {}
bool operator()(X const& item) const {return tid == item.id;}
int tid;
};
std::set<X>::const_iterator find = std::find(data.begin(),data.end(),TestXID(5));
if (find != data.end())
{
// You found the item
}
Upvotes: 2
Reputation: 11981
From your description, you might want to consider using a std::map or std::unordered_map, with your "ID" as the key and your class object as the value.
Upvotes: 2