Как вставить ключ только в одну сторону бимапа в c ++ - PullRequest
1 голос
/ 14 июля 2020

Мне нужно сделать что-то подобное, используя bimap, с тем, что можно сделать с помощью карт нормалей, например

std:map<int, std::string> mymap;

mymap[1];

if(mymap.find(1))
    mymap[1] = "demo";

Аналогичный код, который я пробовал:

#include <string>
#include <iostream>
#include <boost/bimap.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/bimap/multiset_of.hpp>

int main()
{
   typedef boost::bimap<boost::bimaps::set_of<std::string>, boost::bimaps::multiset_of<int>> key_to_id_bimap_t;
   typedef key_to_id_bimap_t::value_type value_type;
   key_to_id_bimap_t bimap;
   
   bimap.right[1];
   
   if(bimap.right.find(1))
   {
       // insert a bunch of value into bimap
   }
}

Есть ли способ добиться этого?

1 Ответ

1 голос
/ 15 июля 2020

Как говорит комментатор, поскольку карты "синхронизированы", вы не можете ожидать редактирования значения одной стороны, потому что это - ключ другой стороны.

Документация есть очень похожий пример, который подчеркивает эти невозможности. см. мое выделение в «operator[] и at() в « Различия со стандартными картами »

Я склонен в пользу MultiIndex. Он имеет те же существенные ограничения / семантику, но, на мой вкус, в нем меньше сюрпризов, потому что он обрабатывает его явным образом. Обратной стороной, конечно же, является то, что вам придется указывать индексы вручную.

MultiIndex Demo

Live On Coliru

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

namespace bmi = boost::multi_index;

struct Entry {
    std::string key;
    int id;
};
using Map = bmi::multi_index_container<Entry,
      bmi::indexed_by<
        bmi::ordered_unique<bmi::tag<struct by_key>,
            bmi::member<Entry, std::string, &Entry::key> >,
        bmi::ordered_non_unique<bmi::tag<struct by_id>,
            bmi::member<Entry, int, &Entry::id> >
      > >;

void dump(std::string_view caption, Map const& bimap) {
    std::cout << caption << ":";
    for (auto& [key,id] : bimap) {
        std::cout << " {" << std::quoted(key) << ", " << id << "}";
    }
    std::cout << "\n";
}

int main() {
    Map bimap;

    auto& left = bimap.get<by_key>();
    auto& right = bimap.get<by_id>();

    // insertions through any index, or just `bumap` which will be the first
    // idex
    right.insert(Entry { "foo", 11 });
    right.insert(Entry { "bar", 22 });
    right.insert(Entry { "qux", 33 });
    assert(bimap.size() == 3);

    auto [it, ok] = right.insert(Entry { "foo", 23 });
    assert(!ok);
    assert(bimap.size() == 3);

    dump("Before", bimap);

    // looking for a single match:
    if (auto it = left.find("foo"); it != left.end()) {
        // to add more relations just insert,
        // to replace the one match found:
        bool ok = left.replace(it, {"something else", it->id}); // okay

        assert(ok);
        assert(it->key == "something else");

        ok = left.replace(it, {"foo", 22}); // id doesn't need to be unique

        assert(ok);
        assert(it->key == "foo");
        ok = left.replace(it, {"bar", 77}); // whoops, duplicate

        assert( ! ok);
        assert(it->key == "foo"); // unchanged
        assert(it->id == 22); // unchanged
    }

    dump("First edit", bimap);

    // query multiple
    for (auto [it,end] = right.equal_range(22); it != end; ++it) {
        // to add more relations just insert,
        // to operate on the match
        bool ok = right.modify(it, [](Entry& match) {
                    match.key = "twenty-two: " + match.key;
                });
        assert(ok);
    }

    dump("Second edit", bimap);
}

Печать

Before: {"bar", 22} {"foo", 11} {"qux", 33}
First edit: {"bar", 22} {"foo", 22} {"qux", 33}
Second edit: {"qux", 33} {"twenty-two: bar", 22} {"twenty-two: foo", 22}

Примечания, заключение:

Как вы Можно видеть, что мультииндекс принимает идиомы replace / modify. Обратите внимание, что modify может быть более эффективным способом обновления, но менее "atomi c" (проверьте документацию, как он ведет себя при конфликте) .

...