c – `std :: unordered_map`没有重复密钥数据

前端之家收集整理的这篇文章主要介绍了c – `std :: unordered_map`没有重复密钥数据前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个Person类,它有一个name属性(std :: string).

我想创建一个查找表,一个std :: unordered_map,所以我可以通过他们的名字找到一个Person.但是,鉴于一个人,我也希望能够得到他们的名字.

这需要存储两次名称 – 一次作为地图的键,一次存在于人物对象内,如下面的代码所示.

由于我有很多人一次加载到内存中,我不希望两次存储他们的名字的开销.

我尝试在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;
}

解决方法

使用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();
    }

};

然后使用它:

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

Demo

猜你在找的C&C++相关文章