如何解决如何合并/连接多个 boost::container::small_vector 并将值作为 boost::any_range 返回?
我有多个 boost::container::small_vector 存储在一个 std::vector 中,我想将 small_vectors 中存储的所有值作为 boost::any_range 返回。你有什么想法我该怎么做吗?
解决方法
当然,您可以以一种非常低效的方式完成,而无需自己编写更多代码:
return boost::accumulate(_storage,R {},[](R&& accum,SV const& sv) { return boost::join(std::move(accum),sv); });
完整演示Live On Godbolt
#include <boost/container/small_vector.hpp>
#include <boost/range/any_range.hpp>
#include <boost/range/join.hpp>
#include <boost/range/numeric.hpp>
#include <fmt/ranges.h>
template <typename T>
struct MyData {
using SV = boost::container::small_vector<T,10>;
using R = boost::any_range<T,boost::bidirectional_traversal_tag>;
R all_view() const {
return boost::accumulate(_storage,sv); });
}
std::vector<SV> _storage;
};
int main() {
MyData<int> ints { { {1,2,3},{4},{5,6,7} } };
fmt::print("ints: {}\n",ints.all_view());
}
印刷品
ints: {1,3,4,5,7}
-
优点:写得快
-
缺点:
- 需要最近的 boost 和编译器
- 为大量子范围生成越来越糟糕的代码:see e.g.
注意简单性:我想象 any_range 使用擦除来发挥它的魔力,这意味着您仍然(逻辑上)有一系列范围,除了现在它可能存储在范围对象的递归树中,每个节点可能会添加一个虚函数调用,以及可能的动态分配。 (虚拟调用可能由非常智能的编译器优化,动态分配可能使用小对象缓冲区优化小范围(作为 QoI 问题),但这仍然限制了范围的可组合性。)
替代方案:
如果可以,请考虑具有 yield_from
的 RangeV3,它可以有效地展平范围,因为它不执行类型擦除。
或者,您可以编写自己的扁平化迭代器。这是更多的工作,但可以通过 boost 进行管理,并将为您提供最佳的预期性能。
#include <boost/container/small_vector.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/optional.hpp>
#include <fmt/ranges.h>
template <typename T>
struct MyData {
using SV = boost::container::small_vector<T,10>;
std::vector<SV> _storage;
struct const_iterator : boost::iterator_facade<const_iterator,T const,boost::forward_traversal_tag> {
using outer = typename std::vector<SV>::const_iterator;
using inner = typename SV::const_iterator;
const_iterator(const_iterator const&) = default;
const_iterator& operator=(const_iterator const&) = default;
const_iterator(outer f,outer l) : _outer(f),_last(l) {
if (_outer != _last)
_inner = _outer->begin();
forward_transport();
}
const_iterator(outer f = {}) : const_iterator(f,f) {}
bool equal(const_iterator const& other) const {
return _outer == other._outer && _inner == other._inner;
}
void increment() {
assert(_outer != _last && _inner != _outer->end());
++_inner;
forward_transport();
}
decltype(auto) dereference() const {
assert(_outer != _last);
return *_inner;
}
protected:
void forward_transport() { // skip over empty subrange(s)
while (_outer != _last && _inner == _outer->end()) {
++_outer;
if (_outer == _last)
_inner = {};
else
_inner = _outer->begin();
}
}
outer _outer,_last;
inner _inner = {};
};
const_iterator begin() const { return {_storage.begin(),_storage.end()}; }
const_iterator end() const { return {_storage.end(),_storage.end()}; }
};
int main() {
MyData<int> ints { { {},{},{ 1,3 },{ 4 },{ 5,7 },{} } };
fmt::print("ints: {}\n",ints);
}
打印(再次/静止):
ints: {1,7}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。