我遇到了一个奇怪的行为,如果你创建一个列表的分块视图,由2个元素组成,然后在一个范围for循环中尝试打印前面和后面,前面的方法可以工作,但后面的方法不行。它会产生一个编译器错误,说示例化.back()方法需要一个双向迭代器。我错过了什么吗?
重现错误的代码
#include <iostream>
#include <list>
#include <ranges>
#include <vector>
int main() {
std::list<int> nums_list = {0, 1, 2, 3, 4, 5};
auto rng = nums_list | std::views::chunk(2);
for (auto pair : rng) {
std::cout << pair.front(); // Front will work normally
std::cout << pair.back(); // No matching member function for 'back'.
}
}
字符串
我也用vector试过了,效果和预期的一样。
1条答案
按热度按时间j7dteeu81#
它将产生一个编译器错误,说明示例化
.back()
方法需要一个双向迭代器。仅当从
view_interface
继承的视图满足forward_range
时才提供front()
成员,并且如果common_range
和bidirection_range
都满足,则提供back()
成员。std::list
满足common_range
和bidirectional_range
,所以rng
也是common_range
和bidirectional_range
†,这允许你在上面使用back()
,例如:字符串
然而,
rng
的值类型,即示例中的pair
,被指定为decltype(views::take(subrange(current_, end_), n_))
†,其中current_
,end_
是std::list
的迭代器。由于
std::list::iterator
不能相减,也就是说它们不满足sized_sentinel_for
,这使得它们构造的subrange
不是sized_range
,最终导致take_view
不是common_range
,所以它的back()
合成失败。†为了支持
back()
,chunk_view
还需要知道底层范围的大小,以找到最后一个块的起始位置。这对std::list
来说不是问题,因为它是sized_range
。<$
views::take
用于自动处理最后一个块的数量小于n
的情况。