来自
Python
的世界,我发现std::iota
的功能非常有限。为什么接口被限制不能取任何UnaryFunction
?
例如我可以转换
>>> x = range(0, 10)
进入
std::vector<int> x(10);
std::iota(std::begin(x), std::end(x), 0);
但是该怎么办:
>>> x = range(0,20,2)
甚至
>>> x = range(10,0,-1)
我知道编写一个这样的函数或使用 Boost 是微不足道的,但我认为 C++ 委员会一定是谨慎选择了这一设计。很明显我错过了 C++11 中的一些东西。
std::generate
?
int n = -2;
std::generate(x.begin(), x.end(), [&n]{ return n+=2; });
int n = 10;
std::generate(x.begin(), x.end(), [&n]{ return n--;});
但是该怎么办:
x = range(0,20,2)
除了
std::generate()
(参见其他答案),您可以向std::iota()
提供您自己的一元函数,只需调用它即可:operator++()
输出:#include <iostream>
#include <functional>
#include <numeric>
#include <vector>
template<class T>
struct IotaWrapper
{
typedef T type;
typedef std::function<type(const type&)> IncrFunction;
type value;
IncrFunction incrFunction;
IotaWrapper() = delete;
IotaWrapper(const type& n, const IncrFunction& incrFunction) : value(n), incrFunction(incrFunction) {};
operator type() { return value; }
IotaWrapper& operator++() { value = incrFunction(value); return *this; }
};
int main()
{
IotaWrapper<int> n(0, [](const int& n){ return n+2; });
std::vector<int> v(10);
std::iota(v.begin(), v.end(), n);
for (auto i : v)
std::cout << i << ' ';
std::cout << std::endl;
}
这是一个如何实现的想法
0 2 4 6 8 10 12 14 16 18
:
Range()
struct Range
{
template<class Value, class Incr>
std::vector<Value> operator()(const Value& first, const Value& last, const Incr& increment)
{
IotaWrapper<Value> iota(first, [=](const int& n){ return n+increment; });
std::vector<Value> result((last - first) / increment);
std::iota(result.begin(), result.end(), iota);
return result;
}
};
static auto stepped_iota(int start, int step) {
return std::ranges::views::iota(0) |
std::ranges::views::transform([=](int x) { return x * step + start; });
}
void f() {
for (int x : stepped_iota(0, 2)) { ... }
}
static auto stepped_iota(int start, int end, int step) {
return std::ranges::views::iota(0, (end - start + step - 1) / step) |
std::ranges::views::transform([=](int x) { return x * step + start; });
}
而不是
iota(0) | stride(2)
这感觉更加笨拙和不必要的计算密集型(即使编译器也许可以从中产生更简单的东西)。