问题描述
哪个更糟?
创建副本
#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,[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 ++ 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;
});
}
如果您真的想要vector
,可以急切地进行评估,但是您可能不需要一次全部使用它了吗?
您也可以使用协程编写生成器(尽管generator<T>
不在标准库中,需要像cppcoro这样使用):
template <class T>
generator<T> range(T start,const T step) {
for (; start < stop; start += stop) {
co_yield start;
}
}
同样,这是一个懒惰范围,可以根据需要将其急切地评估为vector
。
看看boost::irange
。如果那不能满足您的需求,则可以进行一些算术运算。
template<class T>
auto range(const T start,const T step) {
int leaps = ((stop-start)/step);
auto toT = [start,step](int i) { return start + (i * step); };
return boost::irange(0,leaps > 0 ? leaps : -leaps) | boost::adaptors::transformed(toT);
}