c z*_*c z 7 c++ unordered-map stdmap c++11
我有一个Person
类,它有一个name
property(std::string
).
我想创建一个查找表,一个std::unordered_map
,所以我可以找到一个Person
名字.但是,鉴于a Person
,我也希望能够得到他们的名字.
这需要存储name
两次 - 一次作为地图的键,一次存储在人物对象内,如下面的代码所示.
由于我有很多Person
s一次加载到内存中,我不希望两次存储它们的名称的开销.
我已经尝试在Person
类中使用键的引用/指针,但这会产生问题,因为映射似乎在修改时重新调整其数据,并且引用变为无效.
我也尝试过使用std::unordered_set
,但这意味着我Person
每次想要执行查找时都需要构造一个完整的对象.
是否有任何方法可以使无序映射的键和值共享相同的数据?
#include <iostream>
#include <unordered_map>
class Person
{
private:
const std::string _name;
public:
Person( const std::string& name ) : _name( name )
{
}
const std::string& get_name() const
{
return _name;
}
};
int main()
{
auto my_set = std::unordered_map<std::string, std::shared_ptr<Person>>();
my_set.insert( { "alice", std::shared_ptr<Person>( new Person( "alice" )) } );
my_set.insert( { "bob", std::shared_ptr<Person>( new Person( "bob" )) } );
my_set.insert( { "charlie", std::shared_ptr<Person>( new Person( "charlie" )) } );
std::cout << my_set.find( "bob" )->second->get_name() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对于std::set
,您可以使用透明比较器(std::unordered_set
似乎不支持:/):
struct LessPerson
{
using is_transparent = void; // enable "transparent" comparer
template <typename T1, typename T2>
bool operator ()(const T1& t1, const T2& t2) const
{
// Compare only "name".
return toString(t1) < toString(t2);
}
// trivial one
const std::string& toString(const std::string& s) const
{
return s;
}
// the one why we create the class
const std::string& toString(const Person& p) const
{
return p.get_name();
}
// A tricky one to handle dereference of (smart) pointers.
template <typename T,
std::enable_if_t<std::is_same<Person, std::decay_t<decltype(*std::declval<T>())>>::value>* = nullptr>
const std::string& toString(const T& p) const
{
return (*p).get_name();
}
};
Run Code Online (Sandbox Code Playgroud)
然后使用它:
auto my_set = std::set<std::shared_ptr<Person>, LessPerson>();
my_set.insert( { std::make_shared<Person>("alice") } );
my_set.insert( { std::make_shared<Person>("bob") } );
my_set.insert( { std::make_shared<Person>("charlie") } );
auto it = my_set.find("bob"); // search using "bob" directly without creating a new Person
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
658 次 |
最近记录: |