Можно ли вставить forward_list в unordered_map?

Я не заинтересован в том, чтобы заново изобретать колесо. Мне нравится держать код очень компактным, а контейнеры - это то, что мне нравится использовать, чтобы мне не приходилось реализовывать все построчно. Так можно ли использовать эти два контейнера вместе?

1 ответ

Решение

Очевидно, вы можете. Тем не менее, рассмотрим Boost Multi-Index.

демонстрация

Жить на Колиру

#include <unordered_map>
#include <forward_list>
#include <string>

struct Element {
    int id;
    std::string name;

    struct id_equal final : private std::equal_to<int> {
        using std::equal_to<int>::operator();
        bool operator()(Element const& a, Element const& b) const { return (*this)(a.id, b.id); };
    };
    struct name_equal final : private std::equal_to<std::string> {
        using std::equal_to<std::string>::operator();
        bool operator()(Element const& a, Element const& b) const { return (*this)(a.name, b.name); };
    };
    struct id_hash final : private std::hash<int> {
        using std::hash<int>::operator();
        size_t operator()(Element const& el) const { return (*this)(el.id); };
    };
    struct name_hash final : private std::hash<std::string> {
        using std::hash<std::string>::operator();
        size_t operator()(Element const& el) const { return (*this)(el.name); };
    };
};

int main() {

    using namespace std;
    forward_list<Element> const list { { 1, "one" }, { 2, "two" }, { 3, "three" } };

    {
        unordered_map<int, Element, Element::id_hash, Element::id_equal> map;
        for (auto& el : list)
            map.emplace(el.id, el);
    }

    {
        unordered_map<std::string, Element, Element::name_hash, Element::name_equal> map;
        for (auto& el : list)
            map.emplace(el.name, el);
    }
}

Демо с мультииндексом

Это достигает той же цели, но:

  • на месте (без копий контейнера)
  • индексы всегда синхронизированы
  • нет ручных пользовательских объектов хеш / функции равенства

Жить на Колиру

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

struct Element {
    int id;
    std::string name;
};

namespace bmi = boost::multi_index;
using Table = bmi::multi_index_container<Element,
      bmi::indexed_by<
            bmi::hashed_unique<bmi::tag<struct by_id>, bmi::member<Element, int, &Element::id> >,
            bmi::hashed_non_unique<bmi::tag<struct by_name>, bmi::member<Element, std::string, &Element::name> >
         >
      >;

int main() {

    using namespace std;
    Table const list { { 1, "one" }, { 2, "two" }, { 3, "three" } };

    for (auto& el : list.get<by_name>())
        std::cout << el.id << ": " << el.name << "\n";

    for (auto& el : list.get<by_id>())
        std::cout << el.id << ": " << el.name << "\n";
}
Другие вопросы по тегам