Возможно ли создание C++ bimap, если одна сторона представления имеет другой ключ, чем другая сторона значения представления? Как это сделать?
Сначала мне нужна была карта, поэтому я использовал std::map.
Затем были добавлены некоторые требования, и мне нужно было также получить "ключи" для "значения" (foos для бара), поэтому я использовал
boost::bimaps::bimap<
boost::bimaps::unordered_set_of<boost::bimaps::tagged<std::string, foo>>,
boost::bimaps::multiset_of<boost::bimaps::tagged<std::string, bar>>>
И после этого были добавлены еще некоторые требования, так что теперь мне нужно хранить номер для каждого foo и с правой стороны мне нужно иметь возможность звонить <bimap>.righ.find(bar)
и получить пары (foo + число, сохраненное для foo), но я все еще хочу иметь возможность звонить <bimap>.left.find(foo)
и получить бар.
Как этого добиться? Я бы предпочел немного современного C++, чем буста, если это возможно, но я думаю, что сложнее иметь функциональность bimap без буста.
РЕДАКТИРОВАТЬ: я должен отметить, что размер имеет значение, поэтому я не хочу хранить какую-либо часть, участвующую дважды, и скорость также имеет значение.
У меня должно быть что-то вроде "foo1"+100 <-> "bar1"
а также"foo2"+300 <-> "bar4"
,
и я хочу иметь возможность звонить <bimap>.left.find("foo1")
и получить "bar1",
но также <bimap>.right.find("bar1")
и получить пару ("foo1", 100).
1 ответ
#include <boost/multi_index/hashed_index.hpp>
#include <boost/bimap/bimap.hpp>
using namespace std;
struct ElementType {
string foo;
string bar;
uint64_t number;
};
using namespace boost::multi_index;
using my_bimap = multi_index_container<
ElementType,
indexed_by<
hashed_unique<member<ElementType, string, &ElementType::foo>>,
ordered_non_unique<member<ElementType, string, &ElementType::bar>>
>
>;
int main() {
my_bimap instance;
instance.insert({"foo", "bar", 0});
instance.insert({"bar", "bar", 1});
cout << instance.get<0>().find("bar")->foo << endl;
cout << instance.get<0>().find("bar")->bar << endl;
cout << instance.get<0>().find("bar")->number << endl;
auto range = instance.get<1>().equal_range("bar");
for (auto it = range.first; it != range.second; ++it) {
cout << it->foo << endl;
cout << it->number << endl;
}
cin.sync();
cin.ignore();
}
Выход:
bar
bar
1
foo
0
bar
1