我有一个boost :: multiIndex容器。 说:
typedef boost::multi_index<....
> OrderSet;
OrderSet orderSet_;
int main()
{
const auto it = orderSet_.get<0>().equal_range(boost::make_tuple(/* Some Values*/))
if(it.first != it.second)
while(it.second != it.first) { /* Somethings to do */;
--it.second;
}
}
程序因offset_ptr
错误而崩溃。
对于程序it
具有增加订单的价值。所以我想先获得最高价值然后如此...
boost::equal_range(..., [&](const auto a, const auto b)-> decltype bool{return a > b;});
是否有任何过载函数
像这样的东西。它就像reverse_iterator
equal_range()
更新:一个生产者和许多消费者访问多索引容器。当消费者发现equal_range,生成器添加或删除元素时,消费者会抛出错误......这只会在我反向迭代时发生......
答案 0 :(得分:5)
您遗漏了必要部分:所选的索引类型。
不同的索引类型提供不同的接口。
然后,equal_range
意味着有序或无序的地图。因为在无序地图上反转顺序是没有意义的,所以我将假设一个有序的地图。
接下来,使用make_tuple
,我猜测复合键。
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/composite_key.hpp>
struct X {
int i;
std::string name;
};
namespace bmi = boost::multi_index;
typedef boost::multi_index_container<X,
bmi::indexed_by<
bmi::ordered_non_unique<
bmi::tag<struct by_i>,
bmi::composite_key<X,
bmi::member<X, int, &X::i>,
bmi::member<X, std::string, &X::name>
>
>
>
> OrderSet;
然后是原生订单:
#include <iostream>
int main()
{
std::cout << std::unitbuf;
OrderSet orderSet_ {
{ 1, "one" }, { 1, "two" }, { 2, "three" }, { 3, "four" }, { 2, "five" }
};
auto const range = orderSet_/*.get<0>()*/.equal_range(boost::make_tuple(2));
for (auto& el : boost::make_iterator_range(range))
std::cout << el.i << "," << el.name << "; ";
// ...
我使用Boost Range来获得相反的顺序:
#include <boost/range/adaptor/reversed.hpp>
// ...
// traverse these in reverse
std::cout << "\nNow in reverse:\n";
for (auto& el : range | boost::adaptors::reversed)
std::cout << el.i << "," << el.name << "; ";
}
当然你可以手动编写相同内容:
std::cout << "\nAlso in reverse:\n";
auto it = orderSet_.get<0>().equal_range(boost::make_tuple(2));
while(it.second != it.first) {
--it.second;
auto& el = *it.second;
std::cout << el.i << "," << el.name << "; ";
}
<强> Live On Coliru 强>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/range/adaptor/reversed.hpp>
struct X {
int i; // = [] { static int gen = 0; return ++gen; }();
std::string name;
};
namespace bmi = boost::multi_index;
typedef boost::multi_index_container<X,
bmi::indexed_by<
bmi::ordered_non_unique<
bmi::tag<struct by_i>,
bmi::composite_key<X,
bmi::member<X, int, &X::i>,
bmi::member<X, std::string, &X::name>
>
>
>
> OrderSet;
#include <iostream>
int main()
{
std::cout << std::unitbuf;
OrderSet orderSet_ {
{ 1, "one" }, { 1, "two" }, { 2, "three" }, { 3, "four" }, { 2, "five" }
};
{
auto const range = orderSet_/*.get<0>()*/.equal_range(boost::make_tuple(2));
for (auto& el : boost::make_iterator_range(range))
std::cout << el.i << "," << el.name << "; ";
// traverse these in reverse
std::cout << "\nNow in reverse:\n";
for (auto& el : range | boost::adaptors::reversed)
std::cout << el.i << "," << el.name << "; ";
}
{
std::cout << "\nAlso in reverse:\n";
auto it = orderSet_.get<0>().equal_range(boost::make_tuple(2));
while(it.second != it.first) {
auto& el = *(--it.second);
std::cout << el.i << "," << el.name << "; ";
}
}
}
打印
2,five; 2,three;
Now in reverse:
2,three; 2,five;
Also in reverse:
2,three; 2,five;
答案 1 :(得分:1)
更进一步,因为你说offset_ptr
你可能正在使用Boost进程间分配器。
这是一个演示,展示了如何在内存映射/共享内存区域正确执行above:
<强> Live On Coliru 强>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
namespace bmi = boost::multi_index;
namespace bip = boost::interprocess;
//namespace Shared { struct X; }
//namespace std { template<typename Alloc> struct uses_allocator<Shared::X, Alloc> : std::true_type {}; }
namespace Shared {
using Segment = bip::managed_mapped_file;
template <typename T> using Alloc = bip::allocator<T, Segment::segment_manager>;
using String = boost::interprocess::basic_string<char, std::char_traits<char>, Alloc<char> >;
struct X {
using allocator_type = Alloc<char>;
template <typename Alloc>
X(int i, std::string const& s, Alloc alloc) : i(i), name(s.begin(), s.end(), alloc) {}
int i;
String name;
};
typedef boost::multi_index_container<X,
bmi::indexed_by<
bmi::ordered_non_unique<
bmi::tag<struct by_i>,
bmi::composite_key<X,
bmi::member<X, int, &X::i>,
bmi::member<X, String, &X::name>
>
>
>,
Alloc<X>
> OrderSet;
}
#include <iostream>
int main()
{
std::cout << std::unitbuf;
Shared::Segment mmf(bip::open_or_create, "test.data", 10u << 10);
auto& orderSet_ = *mmf.find_or_construct<Shared::OrderSet>("set")(mmf.get_segment_manager());
if (orderSet_.empty()) {
// can't get multi-index to use the scoped allocator "magically" :(
orderSet_.emplace(1, "one", orderSet_.get_allocator());
orderSet_.emplace(1, "one", orderSet_.get_allocator());
orderSet_.emplace(1, "two", orderSet_.get_allocator());
orderSet_.emplace(2, "three", orderSet_.get_allocator());
orderSet_.emplace(3, "four", orderSet_.get_allocator());
orderSet_.emplace(2, "five", orderSet_.get_allocator());
}
{
auto const range = orderSet_/*.get<0>()*/.equal_range(boost::make_tuple(2));
for (auto& el : boost::make_iterator_range(range))
std::cout << el.i << "," << el.name << "; ";
// traverse these in reverse
std::cout << "\nNow in reverse:\n";
for (auto& el : range | boost::adaptors::reversed)
std::cout << el.i << "," << el.name << "; ";
}
{
std::cout << "\nAlso in reverse:\n";
auto it = orderSet_.get<0>().equal_range(boost::make_tuple(2));
while(it.second != it.first) {
auto& el = *(--it.second);
std::cout << el.i << "," << el.name << "; ";
}
}
std::cout << "\nBye\n";
}
打印
2,five; 2,three;
Now in reverse:
2,three; 2,five;
Also in reverse:
2,three; 2,five;
Bye
两次(证明所有数据在共享内存段中都是正确的)。
显然,Boost Multi-Index并没有完全适用于范围分配器,因为它会更优雅:
<强> Live On Coliru 强>
#include <set>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/container/set.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/iterator_range.hpp>
namespace bip = boost::interprocess;
namespace Shared {
using Segment = bip::managed_mapped_file;
template <typename T> using Alloc = bip::allocator<T, Segment::segment_manager>;
using String = boost::interprocess::basic_string<char, std::char_traits<char>, Alloc<char> >;
struct X {
using allocator_type = Alloc<char>;
template <typename Alloc>
X(int i, std::string const& s, Alloc alloc) : i(i), name(s.begin(), s.end(), alloc) {}
bool operator<(X const& other) const { return i < other.i; }
bool operator<(int other) const { return i < other; }
int i;
String name;
};
template <typename T>
using Multiset = boost::container::multiset<
T,
std::less<T>,
boost::container::scoped_allocator_adaptor<Alloc<X> >
>;
using OrderSet = Multiset<X>;
}
#include <iostream>
int main()
{
std::cout << std::unitbuf;
Shared::Segment mmf(bip::open_or_create, "test.data", 10u << 10);
auto& orderSet_ = *mmf.find_or_construct<Shared::OrderSet>("set")(mmf.get_segment_manager());
if (orderSet_.empty()) {
// scoped-allocator automatically propagates to the string
orderSet_.emplace(1, "one");
orderSet_.emplace(1, "one");
orderSet_.emplace(1, "two");
orderSet_.emplace(2, "three");
orderSet_.emplace(3, "four");
orderSet_.emplace(2, "five");
}
{
auto const range = orderSet_.equal_range({2, "", orderSet_.get_allocator()});
for (auto& el : boost::make_iterator_range(range))
std::cout << el.i << "," << el.name << "; ";
// traverse these in reverse
std::cout << "\nNow in reverse:\n";
for (auto& el : range | boost::adaptors::reversed)
std::cout << el.i << "," << el.name << "; ";
}
{
std::cout << "\nAlso in reverse:\n";
auto it = orderSet_.equal_range({2, "", orderSet_.get_allocator()});
while(it.second != it.first) {
auto& el = *(--it.second);
std::cout << el.i << "," << el.name << "; ";
}
}
std::cout << "\nBye\n";
}