首页 > 解决方案 > 一种后增量运算符,允许在指定的步长上进行增量

问题描述

哪个更糟?

创建副本

#include <vector>
#include <algorithm>
template<class T>
std::vector<T> range(const T start, const T stop, const T step) {
    int leaps = ((stop-start)/step);
    std::vector<T> output(leaps > 0 ? leaps : -leaps);
    std::generate(output.begin(), output.end(), [i = start, step] () mutable {
        T num = i;
        i+=step;
        return num;
    });
    return output;
}

或重复(我假设一个计算)。

#include <vector>
#include <algorithm>
template<class T>
std::vector<T> range(const T start, const T stop, const T step) {
    int leaps = ((stop-start)/step);
    std::vector<T> output(leaps > 0 ? leaps : -leaps);
    std::generate(output.begin(), output.end(), [i = start-step, step] () mutable {return i+=step;});
    return output;
}

有没有办法避免两者?诸如后增量运算符之类的东西,其行为类似于i++但允许增量step.

// Example
int main() {
    std::vector<double> check_range = range(-4.13, 2.13, 0.25);
    return 0;
}

预期的

-4.13, -3.88, -3.63, -3.38, -3.13, -2.88, -2.63, -2.38, -2.13, -1.88, -1.63, -1.38, -1.13, -0.88, -0.63, -0.38, -0.13, 0.12, 0.37, 0.62, 0.87, 1.12, 1.37, 1.62, 1.87

标签: c++incrementc++20

解决方案


在 C++20 中,我会懒惰地写它:

template <class T>
auto range(const T start, const T stop, const T step) {
    return views::iota(0)
         | views::transform([=](int i) -> T{
               return i * step + start;
           })
         | views::take_while([=](T cur){
               return cur < stop;
           });
}

如果您真的想要 a vector,您可以急切地评估它,但您可能不需要一次全部?


您还可以使用协程编写生成器(虽然generator<T>不在标准库中,但需要像 cppcoro 一样使用):

template <class T>
generator<T> range(T start, const T stop, const T step) {
    for (; start < stop; start += stop) {
        co_yield start;
    }
}

vector同样,它是一个惰性范围,如果您真的想要,可以急切地将其评估为 a 。


推荐阅读