Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ cppitertools:如何组合iter::enumerate和iter::filter?_C++_Iterator_C++17 - Fatal编程技术网

C++ cppitertools:如何组合iter::enumerate和iter::filter?

C++ cppitertools:如何组合iter::enumerate和iter::filter?,c++,iterator,c++17,C++,Iterator,C++17,考虑这个例子(使用): 预期结果: 4, 5 5, 6 6, 7 7, 8 当我删除iter::enumerate(v)并仅对普通向量进行过滤时,它可以工作: auto f = v | iter::filter([](auto& i) { return i > 4; }); for (auto&& i: f) { std::cout << i << '\n'; } 我可以过滤iter::enumerate()的结果吗?我怀疑我

考虑这个例子(使用):

预期结果:

4, 5
5, 6
6, 7
7, 8

当我删除iter::enumerate(v)并仅对普通向量进行过滤时,它可以工作:

auto f = v | iter::filter([](auto& i) { return i > 4; });

for (auto&& i: f) {
    std::cout << i << '\n';
}

我可以过滤iter::enumerate()的结果吗?我怀疑我在
iter::filter
中得到的lambda函数有误。

iter::enumerate
返回类型为
iter::impl::Enumerable
的实例。它的迭代器一旦被取消引用,就会返回
iter::impl::EnumIterYield
,这是一种从
std::pair
派生的类类型,但也会重新声明自己的数据成员,其
索引(
第一个
)数据成员存储值索引,而
元素
第二个
)是对容器中实际值的引用(请参见
int&
)。这很好,因为我们希望能够通过迭代器修改容器的内容,并避免不必要的副本:

std::vector<int> v{1, 2, 3};
auto e = iter::enumerate(v);
std::get<1>(*e.begin()) = 5;
也就是说,
DerefHolder
专门用于模板参数为引用类型的情况,在这种情况下,它存储(复制可分配)指针。对于非引用类型,实际值存储在
std::optional
(称为
item\u p
)中

对于引用类型,专门化了
DerefHolder
,可以直接使用
iter::impl::filtered::Iterator
对过滤后的容器值进行操作

但是,取消引用的
iter::impl::Enumerable::Iterator
不会产生引用类型。如前所述,它是一个不可复制分配的
iter::impl::EnumIterYield
,它不会触发专门化,而是使编译器返回到
DerefHold
的主模板。其
reset()
函数在找到第一个不应过滤掉的值时调用,具有以下定义:

void reset(T&& item) {
    item_p_ = std::move(item);
}
也就是说,它调用
std::optional::operator=
,然后尝试复制分配有问题的
EnumiteryField
(在没有明确定义复制/移动分配运算符的情况下持有引用类型成员),但操作失败。这是错误消息报告的内容:

error: use of deleted function
我认为没有理由尝试复制并分配存储值,因为它同样可以被重新创建,因此我建议将实现改为复制(移动)-构造存储在
std::optional
中的项:

void reset(T&& item) {
    item_p_.emplace(std::move(item));
}

除非你想得到指数,nevermind@PiotrSkotnicki没错。我也要筛选索引…
iterbase.hpp:301
应该读
item\u p\u.emplace(std::move(item)),而不是
项目\u p\u=std::移动(项目)。也就是说,枚举器的迭代器持有一个引用类型的对,而引用类型是不可复制分配的。@PiotrSkotnicki,所以不能将枚举和筛选结合起来吗?我可以在for循环中显式地进行过滤,但我认为组合迭代器会更优雅…当然,一旦我有时间,我会深入研究一下,以确保我提出了正确的方法谢谢你的回答!我将尝试在cppitertool的github页面上创建一个问题。多么尴尬。谢谢你的深入研究和帮助
template <typename Index, typename Elem>
using EnumBasePair = std::pair<Index, Elem>;

template <typename Index, typename Elem>
class EnumIterYield : public EnumBasePair<Index, Elem> {
    using BasePair = EnumBasePair<Index, Elem>;
    using BasePair::BasePair;

public:
    typename BasePair::first_type index = BasePair::first;
    typename BasePair::second_type element = BasePair::second;
};
// DerefHolder holds the value gotten from an iterator dereference
// if the iterate dereferences to an lvalue references, a pointer to the
//     element is stored
// if it does not, a value is stored instead
void reset(T&& item) {
    item_p_ = std::move(item);
}
error: use of deleted function
void reset(T&& item) {
    item_p_.emplace(std::move(item));
}