![](/img/trans.png)
[英]How to join multiple boost ranges and return as a result from function w/o using boost::any_range
[英]How to merge/concatenate multiple boost::container::small_vector 's and return the values as a 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, R {},
[](R&& accum, SV const& sv) { return boost::join(std::move(accum), 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, 2, 3, 4, 5, 6, 7}
优点:写得快
缺点:
注意简单:我想 any_range 使用擦除来发挥它的魔力,这意味着你仍然(逻辑上)有一系列范围,除了现在它可能存储在范围对象的递归树中,每个节点都可能添加一个虚拟 function 调用,以及可能的动态分配。 (虚拟调用可能由非常智能的编译器优化,动态分配可能使用小对象缓冲区优化小范围(作为 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, 2, 3 }, {}, {}, {}, {}, { 4 }, { 5, 6, 7 }, {} } };
fmt::print("ints: {}\n", ints);
}
打印(再次/仍然):
ints: {1, 2, 3, 4, 5, 6, 7}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.