Vin*_*nci 5 c++ view range custom-view
我目前正在尝试了解即将到来的 std::ranges。作为练习,我想从头开始实现一个“toupper”视图,它对某些字符进行范围/视图并将其转换为大写。
将视图和一些迭代器组合在一起非常简单,我不明白如何操作符()和| 必须重载才能像其他范围一样进行组合。
这是我到目前为止想出的“toupper_fn”(遵循范围命名约定)。这几乎是 v3 范围内某些视图函数的复制/粘贴:
struct toupper_fn {
template <typename Rng>
auto operator()(Rng&& rng) const {
return toupper_view{std::forward<Rng>(rng)};
}
template <typename Rng>
friend auto operator|(Rng&& rng, toupper_fn& c)
-> decltype(c(std::forward<Rng>(rng))) {
return c(std::forward<Rng>(rng));
}
template <typename Rng>
friend auto operator|(Rng&& rng, toupper_fn const& c)
-> decltype(c(std::forward<Rng>(rng))) {
return c(std::forward<Rng>(rng));
}
template <typename Rng>
friend auto operator|(Rng&& rng, toupper_fn&& c)
-> decltype(std::move(c)(std::forward<Rng>(rng))) {
return std::move(c)(std::forward<Rng>(rng));
}
};
Run Code Online (Sandbox Code Playgroud)
问题是,对于这些定义,经典函数调用语法 (view(view...)) 和管道语法,仅当我自己的视图是链中的最后一个时才有效。
这是 godbolt 上的完整代码 ->
使用 range-v3: https: //godbolt.org/z/6RlNVC
或 cmcstl2: https: //godbolt.org/z/wba_yW
好吧,我想通了。初始代码的问题是我的自定义视图既不满足范围也不满足视图概念。那是因为我的迭代器缺少一些特征......
另外,将构造函数参数包装在 range::view::all 中以直接支持容器也是一个好主意。视图“all”根据其输入类型创建无操作、引用包装器或子范围。
这是修改后的工作版本: https ://godbolt.org/z/5YOGNW
/编辑
Chris Di Bella 在 CppCon2019 上的演讲稍微澄清了我答案的第二部分。但他没有包装构造函数参数,而是使用视图本身的推导指南,这当然是首选方式:
template<typename R>
toupper_view(R&&)->toupper_view<ranges::all_view<R>>; // or in ranges v3 -> ranges::cpp20::all_view
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1287 次 |
| 最近记录: |