【问题标题】:How to chain ranges::view conditionally?如何有条件地链接范围::查看?
【发布时间】:2019-11-24 13:42:00
【问题描述】:

简单地说,我如何以编程方式在 view 链结构上分支?

因为现在我能想到的只是#if,这不是一个好主意。

auto adaptor =
   view::drop(x0)
#if branch1
   | view::drop(x1)
#elif branch2
   | view::filter(ft1)
#endif
   | view::stride(s1);

更新

在谷歌上搜索了一段时间后,我认为现在唯一可用的选项是您必须将逻辑“混合”到 view::xxx_while 或任何具有可变 lambda 或其他内容的可预测视图中。

然而,事实证明它已经很不错了。

auto adaptor =
   view::drop(x0)
   | view::drop_while([captures](auto&&) mutable { ...blend it here... })
   | view::filter([captures](auto&&) mutable { ..blend it here... })
   | view::stride(s1);

无论如何,如果view::enable_if 将来可以使用,我认为代码看起来会比这更直接。

【问题讨论】:

  • 我很难理解你的确切意思。你能举个例子吗?
  • @Fureeish 太丑了,不能放在首位。对不起。
  • 鉴于视图是惰性的,它们的声明不应引入任何性能损失。在这种情况下,使用普通的ifs 有什么问题?只需auto rng = prev | ... 等等。范围不太适合这样的分支。它们是轻量级的,可以创建许多它们。未使用的通常不应占用太多(或有时任何)空间。
  • @Fureeish 希望应该有view::enable_if :-)
  • 这些条件是常量表达式吗?

标签: c++ c++20 range-v3


【解决方案1】:

我建议不要这样做。而不是这个假设的代码:

auto adaptor =
   view::drop(x0)
#if branch1
   | ranges::drop(x1)
#elif branch2
   | ranges::filter(ft1)
#endif
   | ranges::stride(s1);

您应该将该逻辑合并到过滤器中:

auto adaptor =
   view::drop(x0)
   | ranges::filter([](auto&& x){ return branch2 && ft1(x); })
   | ranges::stride(s1);

如果你真的想用一些编译时间值组成一个范围适配器,你可以使用这样的 if 语句:

auto get_adapter() {
    if constexpr(branch1)
        return view::drop(x0) | ranges::drop(x1) | ranges::stride(s1);
    else if constexpr (branch2)
        return view::drop(x0) | ranges::filter(ft1) | ranges::stride(s1);
    else
        return view::drop(x0) | ranges::stride(s1);
}

【讨论】:

  • 我解决了我的问题。我只想在一个条件下删除一些并在另一个条件下进行过滤。
  • 不应该是return branch2 && ft1(x);吗?您假设ft1 没有副作用
猜你喜欢
  • 1970-01-01
  • 2014-06-11
  • 1970-01-01
  • 2015-10-06
  • 2011-12-09
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多