【问题标题】:Using a range-v3 view to implement begin()/end() methods使用 range-v3 视图实现 begin()/end() 方法
【发布时间】:2018-02-23 09:49:10
【问题描述】:

是否可以在类内部使用视图来实现 begin() / end() 方法?

例如,我想让下面的类可迭代;在每次迭代 在两个可迭代对象的当前元素上调用 op

template <typename It1, typename It2, typename Op>
struct binary_op {
    binary_op(It1 const& f, It2 const& s, Op o): first{f}, second{s}, op{o} {}

    It1 first;
    It2 second;
    Op op;
};

感谢 range-v3,我可以使用 zip_with 视图(代码未经测试!)

ranges::view::zip_with(op, first, second);

但是我可以使用这个视图实现 begin() / end() 方法吗?

using namespace ranges;

template <typename It1, typename It2, typename Op>
struct binary_op {
    ...

    auto begin() const {
        return view::zip_with(op, first, second).begin();
    }

    auto end() const {
        return view::zip_with(op, first, second).end();
    }
};

两个迭代器(开始和结束)可以安全地比较吗?

我想要实现的最终结果是可以嵌套任意数量的 binary_op:

std::vector<int> v1, v2, v3;

auto r = binary_op(
    binary_op(v1, v2, [](int a, int b) {return a + b;}),
    v3,
    [](int a, int b) {return a - b;});


for (auto x : r) { ... }

【问题讨论】:

    标签: c++ range-v3


    【解决方案1】:

    看起来这样做是安全的,但只存储zip_with_view&lt;...&gt; 而不用打扰binary_op 可能更容易。

    请注意,您的示例不是合法的 C++,因为 lambda 表达式产生的是对象,而不是类型。你需要

    auto op1 = [](int, int) -> int {/*one thing*/};
    auto op2 = [](int, int) -> int {/*other thing*/};
    auto r = binary_op<
        binary_op<decltype(v1), decltype(v2), decltype(op1)>
        decltype(v3),
        decltype(op2)>{ { v1, v2, op1 }, v3, op2 };
    

    此时你还不如

    auto r = view::zip_with(op2,
                            view::zip_with(op1, v1, v2),
                            v3);
    

    【讨论】:

    • 是的,我的代码被破坏了(永远不要在没有测试的情况下发布代码:))我将编辑问题以消除噪音。
    • 我的主要观点是你在复制zip_with的返回类型
    • 我想我会听从你的建议的;我将用范围视图替换我的类,检查适当的视图值类型
    猜你喜欢
    • 1970-01-01
    • 2014-03-18
    • 2020-10-13
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    相关资源
    最近更新 更多