是否存在range :: view :: transform的可修改视图版本? [英] Is there a modifiable-view version of ranges::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&
,我可以将其分配给...
This compiles and prints 10
; but - if I uncomment the (*)
line - it doesn't compile, with GCC complaining about the left side of the equality not being an lvalue. I was kind of disappointed by that - I was sort of hoping the transformation would produce int&
's which I could assign to...
我可以做些修改吗?还是Ranges库中的某些其他机制可以使我获得等同于可修改视图的功能?
Is there something I can to make this a modifiable view? Or some other mechanism in the ranges library which would allow me the equivalent of a modifiable view?
推荐答案
如果考虑一下,代码的问题很简单:
The problem with your code is very simple, if you think about it:
变换功能实际上是投影功能,您不会产生允许修改源代码所需的引用,因为用于普通auto
的规则,而这些规则从不推论引用.
The transformation-function is actually a projection-function, and yours doesn't produce the references necessary for allowing modification of the source, because the standard return type deduction rule for lambdas uses the rules for plain auto
, and those never deduce references.
-
一个解决方案正在更改
decltype(auto)
的扣除规则,它保留了引用,因此最好避免使用,除非您知道它们是正确的.
auto int_view = tuples | ranges::view::transform(
[](auto& t)->decltype(auto){return std::get<int>(t);});
或者您可以使用auto&
或更具体的内容来明确要求引用.
Or you can explicitly ask for references with auto&
or something more specific.
auto int_view = tuples | ranges::view::transform(
[](auto& t)->auto&{return std::get<int>(t);});
最后,没有人阻止您返回像std::reference_wrapper
这样的代理.虽然这是不必要的并发症.
And finally nobody stops you from returning a proxy like std::reference_wrapper
. Though that's a needless complication.
auto int_view = tuples | ranges::view::transform(
[](auto& t){return std::ref(std::get<int>(t));});
这篇关于是否存在range :: view :: transform的可修改视图版本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!