我的类表现得像一个懒惰的容器,可以动态生成值。然后在某些情况下,我想过滤值。 Boost :: range :: adapters :: filtered似乎非常适合。但是它没有保留对“范围”的任何引用,它只存储开始/结束迭代器。
以下代码模仿我的用例。但它不起作用:container
在使用r
之前被销毁。
#include <iostream>
#include <vector>
#include <boost/range/adaptor/filtered.hpp>
#define PING() std::cerr << __PRETTY_FUNCTION__ << '\n'
using ints = std::vector<int>;
struct container
{
container() { PING(); }
~container() { PING(); }
using value_type = typename ints::value_type;
using iterator = typename ints::iterator;
using const_iterator = typename ints::const_iterator;
iterator begin() { PING(); return std::begin(c_); }
iterator end() { PING(); return std::end(c_); }
const_iterator begin() const { PING(); return std::cbegin(c_); }
const_iterator end() const { PING(); return std::cend(c_); }
ints c_ = { 1, 2, 3, 4, 5 };
};
int main()
{
auto r = container{} | boost::adaptors::filtered([](auto&& v) { return v % 2; });
std::cerr << "Loop\n";
for (auto i: r)
std::cout << i << '\n';
}
结果是(live code):
container::container()
const_iterator container::begin() const
const_iterator container::end() const
const_iterator container::end() const
const_iterator container::end() const
container::~container()
Loop
1
3
5
有没有一种简单的方法可以确保每个人只要我需要就活着?当然在main
中我可以声明一个变量来存储container{}
,但这对于我的真实世界使用来说是不合适的,因为这个容器实际上是通过查询一些对象获得的;我不希望客户方必须处理这个问题。
似乎最简单的是重写某些版本的filtered
来保留范围的副本,但我想寻找一种避免编写过多代码的解决方案。而且我真的在寻找Range-v2解决方案:对我来说,依赖Range-v3可能还为时过早。
答案 0 :(得分:1)
所以这很讨厌。
诀窍是你必须首先存储容器 ,然后将管道应用到存储容器,然后假装是那个范围。
template<class X>struct store{ X data; };
template<class Src, class Range>
struct save_src_range:
private store<Src>,
Range
{
// boilerplate for copy/move goes here (TODO)
template<class S, class RangeFactory>
save_src_range( S&& s, RangeFactory&& f ):
store<Src>{std::forward<S>(s)},
Range( std::forward<RangeFactory>(f)(this->data) )
{}
};
现在需要通过演绎创作功能等来加以理解。
接下来,我们需要一种语法上非常好的方式将该功能插入到现有语法中。
一种方法是:
keep_a_copy( source ) | boost::adapters::filter( ... blah ... )
我们做一些柔道,让它神奇地工作,甚至可能在链接之后。
或者
source | keep_source_copy( boost::adapters::filter( ... blah ... ) )
我认为这有点容易。
我对它进行了一次刺痛,这是非常痛苦的,但我没有看到任何根本不可能的东西。它肯定涉及编写太多代码。