这里有一种方法来实现你想要的。
它使用boost::multi_index
提供的一些技术。
请注意使用project
将一个索引中的迭代器转换为另一个索引中的迭代器。
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
namespace example {
struct by_id {};
struct by_insertion_order {};
using namespace boost;
using namespace boost::multi_index;
using item_type = std::pair<int, int>;
typedef multi_index_container<
item_type, // what we are storing
indexed_by<
// unordered multimap-type index
hashed_non_unique<tag<by_id>, member<item_type, int, &item_type::first> >,
// sequence-type index - records insertion order
sequenced<tag<by_insertion_order>>
>
> my_store;
using const_insertion_sequence_iterator = decltype(std::declval<my_store>().get<by_insertion_order>().cbegin());
using const_by_id_iterator = decltype(std::declval<my_store>().get<by_id>().cbegin());
// convert a range of 'by_id' iterators to an ordered vector 'by_insertion_sequence' iterators
// @param store is a reference to the store for which the iterators are valid
// @param first is the first by_id iterator in the filtered range
// @param last is the 'one past the end' iterator of the filtered range
// @returns a vector of iterators to items ordered by insertion sequence
auto
projected_to_insertion_order(const my_store& store,
const_by_id_iterator first,
const_by_id_iterator last)
-> std::vector<const_insertion_sequence_iterator>
{
std::vector<const_insertion_sequence_iterator> result;
for (; first != last ; ++first) {
result.push_back(store.project<by_insertion_order>(first));
}
sort(result.begin(),
result.end(),
[&store](const auto& il, const auto& ir) {
return distance(store.get<by_insertion_order>().cbegin(), il)
< distance(store.get<by_insertion_order>().cbegin(), ir);
});
return result;
}
}
int main()
{
using namespace std;
using example::my_store;
using example::by_id;
using example::by_insertion_order;
using example::projected_to_insertion_order;
// define store
my_store m;
// add some items
m.get<by_id>().emplace(1,2);
m.get<by_id>().emplace(3,6);
m.get<by_id>().emplace(1,3);
m.get<by_id>().emplace(2,5);
m.get<by_id>().emplace(1,4);
// get range of items filtered by id
auto ip = m.get<by_id>().equal_range(1);
cout << "filtered but unordered\n";
for (auto it = ip.first ; it != ip.second ; ++it) {
cout << it->first << ":" << it->second << endl;
}
// project that to a vector of iterators to items ordered by insertion sequence
cout << "filtered and ordered by insertion sequence\n";
for (const auto& it : projected_to_insertion_order(m, ip.first, ip.second)) {
cout << it->first << ":" << it->second << endl;
}
}
预期输出:
filtered but unordered
1:4
1:3
1:2
filtered and ordered by insertion sequence
1:2
1:3
1:4
不,这不是。你会想看看提振多索引 –
我想这个名字明确表示它是一个无序地图。你不能指望任何特定的顺序。 –