是否有 ranges::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&
,我可以将其分配给...
有什么办法可以使它成为可修改的视图吗?或者范围库中的一些其他机制允许我等效于可修改的视图?
你的代码问题很简单,你想想看:
转换函数实际上是一个投影函数,您的函数不会生成允许修改源代码所必需的引用,因为 the standard return type deduction rule for lambdas uses the rules for plain auto
,并且那些从不推导出引用。
One fix is changing to the deduction rules for 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));});
考虑以下程序:
#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&
,我可以将其分配给...
有什么办法可以使它成为可修改的视图吗?或者范围库中的一些其他机制允许我等效于可修改的视图?
你的代码问题很简单,你想想看:
转换函数实际上是一个投影函数,您的函数不会生成允许修改源代码所必需的引用,因为 the standard return type deduction rule for lambdas uses the rules for plain auto
,并且那些从不推导出引用。
One fix is changing to the deduction rules for
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));});