主要是作为一个练习我实现从基地B
转换立足10
:如何减少迭代器的样板?
unsigned fromBaseB(std::vector<unsigned> x,unsigned b){
unsigned out = 0;
unsigned pow = 1;
for (size_t i=0;i<x.size();i++){
out += pow * x[i];
pow *= b;
}
return out;
}
int main() {
auto z = std::vector<unsigned>(9,0);
z[3] = 1;
std::cout << fromBaseB(z,3) << std::endl;
}
现在我想写这使用的算法。例如。使用accumulate
我可以写
unsigned fromBaseB2(std::vector<unsigned> x,unsigned b){
unsigned pow = 1;
return std::accumulate(x.begin(),
x.end(),0u,
[pow,b](unsigned sum,unsigned v) mutable {
unsigned out = pow*v;
pow *= b;
return out+sum;
});
}
但是,我认为这不是更好的代码。事实上,将它作为内部产品写入会更自然,因为这正是我们必须计算的基础变革。但使用inner_product
我需要一个迭代器:
template <typename T> struct pow_iterator{
typedef T value_type;
pow_iterator(T base) : base(base),value(1) {}
T base,value;
pow_iterator& operator++(){ value *= base;return *this; }
T operator*() {return value; }
bool operator==(const pow_iterator& other) const { return value == other.value;}
};
unsigned fromBaseB3(std::vector<unsigned> x,unsigned b){
return std::inner_product(x.begin(),x.end(),pow_iterator<unsigned>(b),0u);
}
使用迭代器,现在称该算法是不错的干净,但我不得不写大量的样板代码的迭代器。也许这只是我对算法和迭代器应该如何使用的误解......实际上,这只是我常常遇到的一个普遍问题的一个例子:我有一系列基于简单模式计算的数字,而我想要有一个迭代器,当解除引用时返回该序列中相应的数字。当序列存储在一个容器中时,我只需使用容器提供的迭代器,但我也希望这样做,当没有容器存储值时也是如此。我当然可以尝试编写自己的通用迭代器来完成这项工作,但是标准库中是否存在可以帮助您的工作?
对我来说,感觉有点怪怪的,我可以使用lambda欺骗accumulate
成计算内积,而是利用inner_product
直接我必须做些额外的事情(无论是预先计算的权力,并将它们存储在一个容器中,或者写一个迭代器,即单独的class
)。
tl; dr:是否有简单的方法来减少上述pow_iterator
的样板?
更一般的问题(但可能太宽泛)问题:对于未存储在容器中的值序列使用迭代器是否“正常”,但仅在迭代器被解除引用时才计算?有没有实现它的“C++方法”?
看看boost.iterator库。特别是iterator_adapter和iterator_facade。 –