【问题标题】:Is there a modifiable-view version of ranges::view::transform?是否有范围::view::transform 的可修改视图版本?
【发布时间】:2019-04-21 22:38:03
【问题描述】:

考虑以下程序:

#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&amp;'s 我可以分配给...

有什么办法可以使它成为可修改的视图吗?还是范围库中的其他一些机制可以让我等效于可修改的视图?

【问题讨论】:

    标签: c++ range-v3


    【解决方案1】:

    如果你仔细想想,你的代码的问题很简单:

    转换函数实际上是一个投影函数,您的函数不会产生允许修改源所需的引用,因为the standard return type deduction rule for lambdas 使用rules for plain auto,而那些永远不会推导出引用。

    1. 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);});
      
    2. 或者您可以明确要求使用auto&amp; 或更具体的方式提供参考。

      auto int_view = tuples | ranges::view::transform(
          [](auto& t)->auto&{return std::get<int>(t);});
      
    3. 最后没有人阻止你返回像std::reference_wrapper 这样的代理。虽然这是一个不必要的并发症。

      auto int_view = tuples | ranges::view::transform(
          [](auto& t){return std::ref(std::get<int>(t));});
      

    【讨论】:

    • @einpoklum 我详细说明了。
    • 那么,-&gt;auto 也不会推断出引用,而decltype(auto) 会推断出一个?有趣的。好吧,没那么有趣,但很重要。
    猜你喜欢
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    • 1970-01-01
    • 1970-01-01
    • 2011-11-02
    • 2015-11-02
    相关资源
    最近更新 更多