我有一个类似的数据结构,如下所示:
struct Data { std::string id; Blob data; };
现在我可以使用std::map
来存储结构并按ID进行搜索,但我正在寻找一种方法来使用std::set
实现同样的功能(因为我真的不需要分离ID和结构(。
std::set::find
当然将密钥类型作为参数,所以我可以(使用适当的构造函数(这样做:
set<Data> x; x.find(Data("some_id"));
但如果可能的话,我想避免这种情况。这需要有一个允许ID不带数据的构造函数,而且我真的不喜欢构造对象,只是把它用作搜索的关键字。
所以我的问题是:有更好的方法吗?
除非开销明显不可接受,否则我会选择std::map<std::string, Data *>
,或者可能是std::map<std::string, boost::shared_ptr<Data> >
,假设您无法访问本机提供shared_ptr的编译器。
加上几个构造函数和一个operator<
,事情就变得非常容易了。
struct Data {
std::string id;
Blob data;
Data(const char* r) : id(r), data() {}
bool operator<(const Data & r) const {return id<r.id;}
// rest not needed for demo, but handy
Data() : id(), data() {}
Data(std::string&& r) : id(std::move(r)), data() {}
Data(const std::string& r) : id(r), data() {}
Data(Data && r) : id(r.id), data(r.data) {}
Data(const Data & r) : id(r.id), data(r.data) {}
~Data() {}
};
int main() {
std::set<Data> x;
x.insert("Apple");
x.insert("Banana");
x.insert("Orange");
x.insert("Grape");
std::set<Data>::iterator i = x.find("Banana");
if (i != x.end())
std::cout << i->id;
else
std::cout << "ERR";
}
http://ideone.com/nVihc结果:
香蕉
我承认,这仍然创建了一个"伪"数据实例,但它似乎解决了问题。
如果您不反对使用Boost,那么Boost.MultiIndex会让这变得非常简单,而不会添加任何不必要的低效率。以下是一个有效创建Data
对象的set
的示例,该对象以Data::id
:的值为键
#include <string>
#include <ios>
#include <iostream>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
namespace bmi = boost::multi_index;
typedef char const* Blob;
struct Data
{
std::string id;
Blob data;
void display() const { std::cout << "id: " << id << 'n'; }
};
typedef bmi::multi_index_container<
Data,
bmi::indexed_by<
bmi::ordered_unique<
bmi::member<Data, std::string, &Data::id>
>
>
> DataSet;
int main()
{
Data d1 = { "some_id", nullptr };
Data d2 = { "some_other_id", nullptr };
DataSet set;
set.insert(d1);
set.insert(d2);
set.find("some_id")->display();
// for exposition, find is actually returning an iterator
DataSet::const_iterator iter = set.find("some_other_id");
if (iter != set.end())
iter->display();
// set semantics -- newly_added is false here, because the
// container already contains a Data object with id "some_id"
Data d3 = { "some_id", "blob data" };
bool const newly_added = set.insert(d3).second;
std::cout << std::boolalpha << newly_added << 'n';
}
更好的方法是让id
索引data
。但由于您不想这样做,请尝试使用std::find_if( x.first(), x.end(), --predicate-- )
,其中谓词是一个函数对象或lambda函数谓词,用于将Data
与指定的id
进行比较。
我意识到这个问题是在可能之前提出的,但是:
从C++14开始,可以在一个集合中进行搜索,而无需创建密钥类型的实例,只需使用模板化密钥的std::set::find的额外重载。