Правильный способ создания и управления поиском контейнеров - PullRequest
0 голосов
/ 01 февраля 2019

правильный способ создания поисковых карт для экземпляров.У меня есть структура, определенная Node следующим образом:

struct Node
{
    int32_t id;
    std::string name;
    ...
}

Я хочу создать 2 карты поиска на основе идентификатора, а другой - на основе имени.В узле есть и другие атрибуты, которые также должны искать карты, но они динамические, поэтому не у каждого экземпляра узла будет запись взгляда на эти дополнительные карты.

только с одной картой поиска, которую я планировал создатькак

typedef std::unoredered_map<int32_t, std::unique_ptr <Node> > NodesById;

Я считаю, что просто могу удалить это, просто erase или [id] = new 'overwrite!' операция и не нужно беспокоиться об этом.Но тогда как я могу добавить тот же экземпляр Node, чтобы сказать другую карту

typedef std::unoredered_map<std::string, std::unique_ptr <Node> > NodesByName;

Я не могу поместить тот же экземпляр Node в unique_ptr.Поэтому мой вопрос заключается в том, как правильно хранить экземпляры Node в нескольких справочных таблицах и при этом достигать интеллектуального управления памятью.

1 Ответ

0 голосов
/ 01 февраля 2019

Использование boost::multi_index:

#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <string>    
#include <cassert>    

struct Node {
    int32_t id;
    std::string name;

    Node(int32_t id, std::string name)
        : id(id)
        , name(move(name))
    {}

    // Just to demonstrate that Node doesn't need to be copyable/moveable.
    Node(Node const&) = delete;
    Node& operator=(Node const&) = delete;
};

namespace mi = boost::multi_index;

using NodeSet = mi::multi_index_container<
      Node
    , mi::indexed_by<
            mi::hashed_unique<mi::member<Node, int32_t, &Node::id>>
          , mi::hashed_unique<mi::member<Node, std::string, &Node::name>>
      >
    >;

int main() {
    NodeSet s;
    s.emplace(1, "Alice");
    s.emplace(2, "Bob");

    assert(s.find(1)->name == "Alice");
    assert(mi::get<0>(s).find(1)->name == "Alice"); // Same as above.
    assert(mi::get<1>(s).find("Alice")->id == 1);
}

Хранение по значению более эффективно, чем сохранение unique_ptr в нем.И поскольку NodeSet не требует Node для копирования или перемещения, нет необходимости использовать unique_ptr здесь.

...