【问题标题】:Repeat n times with C++ ranges without dummy variable使用没有虚拟变量的 C++ 范围重复 n 次
【发布时间】:2022-01-17 00:33:50
【问题描述】:

我正在尝试使用 C++20 范围实现重复 n 次。 works,但我能想到的所有方法都需要一个虚拟变量(一个用于 for 循环变量,另一个用于 lambda 的数量)。

static constexpr int kIterations = 3;

void f1(){
    auto c = '.';
    for (const auto _ :std::views::iota(0)| std::views::take(kIterations) ) {
        std::cout << c;
    }
    std::cout << std::endl;
}

void f2(){
    auto c = '.';
    std::ranges::for_each(std::views::iota(0)| std::views::take(kIterations), [&c](const auto _) {
        std::cout << c;
    });
    std::cout << std::endl;
}

有没有一种方法可以在不需要虚拟变量的情况下使用 C++20 范围执行此操作(在我的情况下为 _,但即使未命名也需要 const?auto)。

注释:

  • 我知道我可以使用 C for 循环????,我有兴趣以 C++20 范围的方式执行此操作。
  • 我想我可以自己在算法中实现这一点,但我想知道我是否可以在不实现 repeat_n 的情况下“内联”实现它
  • 我知道 iota 的版本需要 2 个整数,它可能更具可读性,但仍然不能解决虚拟变量的问题。
  • 逻辑被简化,只是为了展示捕获

【问题讨论】:

  • range-v3 有views::repeatviews::repeat_n
  • 在 lambda 中你至少可以省略命名变量。
  • 转换iota视图也使用了一个虚拟变量for (const auto e : std::views::iota(0, kIterations) | std::views::transform([&amp;c](int){ return c }) { std::cout &lt;&lt; e; }
  • @super true,我的错,但它仍然需要 auto/const auto
  • @NoSenseEtAl,你能澄清一下你想做什么吗?您是否尝试依赖 C++20 的 &lt;ranges&gt; 在 C++20 中实现 Range-v3 的 repeat_n?如果是这样,f1f2 在调用repeat_n([&amp;c](const auto _) { std::cout &lt;&lt; c; }) 时是否符合您的预期?我已经给出了答案,但后来删除了它,因为我认为我误解了。

标签: c++ c++20 std-ranges


【解决方案1】:

范围是一种迭代一组值的方法。您可以按需制造这些值,而不是像iota 那样从存储中访问它们。但是范围是关于迭代一系列值。

因此,任何基于范围的迭代机制都将涉及一个对象,该对象至少表示范围中的当前位置。这就是野兽的本性。

是的,您可以编写自己的 ranges::for_each 版本,它“迭代”一个范围,但实际上并不将这些值传递给函子:

template<std::ranges::input_range Rng, std::invocable Func>
decltype(auto) iterate_no_element(Rng &&rng, Func func)
{
  return std::ranges::for_each(std::forward<Rng>(rng), [func](auto const&){func();})
}

但标准没有这样的功能。

【讨论】:

    【解决方案2】:

    如果您可以同时使用 Range-v3 中的 C++20 &lt;ranges&gt;repeat_n,那么这可能是一种方法吗?

    #include <algorithm>
    #include <functional>
    #include <iostream>
    #include <boost/hof/lift.hpp>
    #include <range/v3/view/repeat_n.hpp>
    #include <ranges>
    
    using ranges::views::repeat_n;
    using namespace std::ranges::views;
    using namespace std::ranges;
    
    auto constexpr invoke = BOOST_HOF_LIFT(std::invoke); // what a pity we need this
    
    static constexpr int kIterations = 3;
    
    void f() {
        char c = '.';
        for_each(repeat_n([c]{ std::cout << c << std::endl; },
                          kIterations),
                 invoke);
    }
    
    int main()
    {
        f();
    }
    

    lambda [c]{ std::cout &lt;&lt; c &lt;&lt; std::endl; } 是空值,因为它没有传递任何值,并且没有带有虚拟变量的 for 循环。

    【讨论】:

      猜你喜欢
      • 2012-08-21
      • 1970-01-01
      • 2019-09-28
      • 1970-01-01
      • 2020-09-28
      • 2023-03-14
      • 2018-07-15
      • 2016-05-04
      • 2010-12-07
      相关资源
      最近更新 更多