2009-12-29 94 views
0

所以我正在研究一个项目,并且我必须在类对象上使用set库。这些对象有许多属性,ID就是其中之一。如何使用类作为在set :: find()上使用的值? - C++

我想要做的是通过它的ID搜索“set”内的对象。问题设置只有找到,我不知道如何搜索一个ID这种方式,因为我不得不使用find(类对象),而不是(int)。我试图搞乱类操作符,把它当作一个对象来读取,但是找不到方法。

另外,我想过算法:: find_if,但这只是检查每个元素从开始到结束,而不是使用设置的“树”搜索功能,对不对?

在此先感谢。

回答

0

你需要为你的类创建一个构造函数,它只需要int作为它的唯一参数。这样做可以将int隐式转换为您的班级,从而可以根据要求拨打std::set::find(int)

例如:

#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; 
} 

这产生了:

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 
+0

这完全是我想知道的。现在正在工作,谢谢! – user228938 2009-12-29 21:34:21

2

您必须使用第二个模板参数来指定比较函子。看你的ltstr例子this page

+0

的事情是我已经做了,由于这是需要在设置正确插入类。这也是工作,因为它根据他们的ID插入它们,但是发现它仍然不会让我使用find(int)... – user228938 2009-12-29 19:32:46

+0

是的,你必须用你想要的ID做一个虚拟实例。 – Pace 2009-12-29 19:34:35

2

从你的描述中,你可能要考虑使用一个std :: map或std :: unordered_map,其中你的“ID”作为键,你的类对象作为值。

+0

我同意这一点,但他的问题表明他必须使用std :: set。 – 2009-12-29 19:39:34

2

如果你的类是一组,那么你已经定义了运营商<或提供了一个具体的比较器使用比较元素已经compatable严格的弱秩序。

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 
} 

这在你需要的方式,你可以很容易地与特定的ID和运营商<(或比较器)创建的临时对象来定义X的缺点仅仅是ID的严格弱序。

另一种方法是使用std :: find_if()使用自定义比较器:

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 
} 
+0

正如前面提到的海报,std :: find_if()的缺点是它在复杂度上是线性的,与std :: set :: find()的O(log n)相反。 – mrkj 2009-12-29 20:25:07