c++ - 是否有范围::view::transform 的可修改视图版本?
问题描述
考虑以下程序:
#include <iostream>
#include <algorithm>
#include <numeric>
#include <array>
#include <range/v3/view/transform.hpp>
int main() {
using container = std::array<std::tuple<int,float,double>, 4>;
container tuples {{
{1, 4.f, 8.},
{2, 5.f, 9.},
{3, 6.f, 10.},
{4, 7.f, 11.}
}};
auto int_view =
tuples | ranges::view::transform( [](auto& t){return std::get<int>(t);} );
// int_view[1] = 3; // (*)
auto x = std::accumulate(int_view.begin(), int_view.end(), 0);
std::cout << "x = " << x << std::endl;
}
这会编译并打印10
;但是 - 如果我取消注释该(*)
行 - 它不会编译,GCC 抱怨等式的左侧不是左值。我对此有点失望——我有点希望这种转变会产生int&
我可以分配给...
有什么我可以使它成为可修改的视图吗?或者范围库中的其他一些机制可以让我相当于一个可修改的视图?
解决方案
如果您考虑一下,您的代码的问题非常简单:
转换函数实际上是一个投影函数,您的函数不会产生允许修改源所需的引用,因为lambdas 的标准返回类型推导规则使用plainauto
的规则,而那些从不推导引用。
一种解决方法是更改 的扣除规则
decltype(auto)
,它保留引用,因此最好避免,除非您知道它们是正确的。auto int_view = tuples | ranges::view::transform( [](auto& t)->decltype(auto){return std::get<int>(t);});
或者,您可以明确要求提供
auto&
更具体的参考。auto int_view = tuples | ranges::view::transform( [](auto& t)->auto&{return std::get<int>(t);});
最后没有人阻止你返回一个像
std::reference_wrapper
. 虽然这是一个不必要的并发症。auto int_view = tuples | ranges::view::transform( [](auto& t){return std::ref(std::get<int>(t));});
推荐阅读
- jquery - 有没有办法使用 JQuery 从 css 类中获取类定义或值?
- php - 使用 PHP 从数据库中检索图像并在 Flutter 项目中使用(在 Dart 中)
- c# - C#“访问路径被拒绝”netcore linux/raspbian 如何获得写入系统文件的访问权限
- java - 两个模式之间的Java正则表达式匹配
- python - 如何旋转 matplotlib 地图?
- hibernate - 无法建立实体管理器工厂-Hibernet AWS
- django - Django 正在验证没有为必填字段选择值的表单集
- django - 多对多关系 - 电影 - 角色 - 演员
- javascript - forEach 中用于 redux 减速器的突变(使用 immer.js)
- flutter - 如何更改 Scaffold 小部件的抽屉颜色