问题描述
我使用带有 std::back_inserter
的 std::transform
将元素附加到 std::deque
.现在,在某些情况下,转换可能会失败并返回无效对象(比如未初始化的 boost::optional
或空指针).我想从附加中过滤掉无效对象.
I am using std::transform
with an std::back_inserter
to append elements to an std::deque
. Now the transformation may fail and will return a invalid object (say an uninitialized boost::optional
or a null pointer) in some cases. I would like to filter out the invalid objects from getting appended.
我考虑过使用 boost::filter_iterator
,但不确定如何呈现过滤范围的 end()
参数.
I thought about using boost::filter_iterator
, but not sure how to present the end()
parameter of the filtered range.
boost::filter_iterator
的文档表明输出过滤是可能的.在这种情况下,我是否应该专门为 std::back_insert_iterator
指定 operator ==
以始终返回 false?
The documentation of boost::filter_iterator
suggests that output filtering is possible. Should I just specialize operator ==
for std::back_insert_iterator
in this case to always return false?
除此之外,如果我想附加初始化的 boost::optional
或指针的值,我可以链接 boost::filter_iterator
和 boost::indirect_iterator
?
In addition to this, if I want to append values of initialized boost::optional
or pointers, can I chain boost::filter_iterator
and boost::indirect_iterator
?
我试图避免推出我自己的 transform_valid
函数,该函数采用可选的 extractor
函数.
I am trying to avoid rolling out my own transform_valid
function that takes an optional extractor
function.
是否可以使用 filter_iterator
作为输出迭代器?
Is it even possible to use filter_iterator
as an output iterator?
推荐答案
为了方便使用,我建议使用 boost range(算法和适配器),你会写:
I suggest using boost range (algorithms & adaptors) for ease of use, you'd write:
boost::copy(
data | transformed(makeT) | filtered(validate) /* | indirected */,
std::back_inserter(queue));
这是一个完整的工作示例:
Here is a complete working example of that:
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/optional.hpp>
#include <vector>
#include <deque>
typedef boost::optional<int> T;
typedef std::deque<T> Q;
static T makeT(int i)
{
if (i%2) return T();
else return i;
}
static bool validate(const T& optional)
{
return (bool) optional; // select the optional that had a value set
}
int main()
{
static const int data[] = { 1,2,3,4,5,6,7,8,9 };
Q q;
using boost::adaptors::filtered;
using boost::adaptors::transformed;
// note how Boost Range elegantly supports an int[] as an input range
boost::copy(data | transformed(makeT) | filtered(validate), std::back_inserter(q));
// demo output: 2, 4, 6, 8 printed
for (Q::const_iterator it=q.begin(); it!=q.end(); ++it)
{
std::cout << (*it? "set" : "unset") << " " << it->get_value_or(0) << std::endl;
}
return 0;
}
更新
从这个答案中得到一点帮助:使用 boost::optional 和 boost::adaptors::间接
With a little help from this answer: Use boost::optional together with boost::adaptors::indirected
我现在包含了一个使用 indirected
范围适配器以及队列的直接输出的优雅演示(取消引用选项):
I now include an elegant demonstration of using the indirected
range adaptor as well for immediate output of the queue (dereferencing the optionals):
请注意,对于(智能)指针类型,显然不需要提供 pointee<>
特化.我认为这是设计使然:可选<>不是,也不建模,指针
Note that for (smart) pointer types there would obviously be no need to provide the
pointee<>
specialisation. I reckon this is by design:optional<> is not, and does not model, a pointer
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/optional.hpp>
namespace boost {
template<typename P> struct pointee<optional<P> > {
typedef typename optional<P>::value_type type;
};
}
typedef boost::optional<int> T;
static T makeT(int i) { return i%2? T() : i; }
static bool validate(const T& optional) { return (bool) optional; }
int main() {
using namespace boost::adaptors;
static int data[] = { 1,2,3,4,5,6,7,8,9 };
boost::copy(data | transformed(makeT)
| filtered(validate)
| indirected,
std::ostream_iterator<int>(std::cout, ", "));
}
这篇关于是否可以使用 boost::filter_iterator 进行输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!