为何无法对const修饰的ranges::any_view调用ranges::begin?
ranges::any_view的const调用问题
问题代码与核心疑惑
以下代码执行失败:
#include <range/v3/view/any_view.hpp> #include <vector> int main() { std::vector<int> a{1}; const ranges::any_view<int, ranges::category::forward> av(a); ranges::begin(av); }
我原本认为begin会返回支持多次遍历的新迭代器,为什么它要求范围必须是可修改的?
我的实际代码场景如下:
void merge(ranges::any_view<int, ranges::category::forward> av) { for(auto x : av) { ... } }
clang-tidy警告我应该把av改成const&,因为按值传递但没有在函数体内移动它,但改成const引用就会触发前面的调用失败问题。
对原因的推测
我怀疑这和begin/end调用的均摊常数时间复杂度要求有关。比如下面这段代码也会执行失败,原因应该是const的drop视图无法缓存begin的迭代器:
std::list<int> b{1, 2, 3, 4}; const auto latter = ranges::views::all(b) | ranges::views::drop(2); ranges::begin(latter);
为了兼容这类被包装的视图,any_view需要缓存首次调用begin的结果,这就要求它能修改自身状态——因此const修饰的any_view无法调用begin,哪怕把类别改成random_access也不行:
const ranges::any_view<int, ranges::category::random_access> av(a);
寻求绕过方案
如果这确实是input类别下失败的原因,有没有什么绕过方法?比如类似C++23中std::move_only_function对std::function的移动语义扩展那样的方案?
内容的提问来源于stack exchange,提问作者Johannes Schaub - litb
相关产品推荐
相关产品推荐

