主要是作为练习我正在实施从基础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;
});
}
然而,imho根本不是更好的代码。实际上将它作为内部产品编写会更自然,因为这正是我们必须计算的基础转换。但要使用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);
}
使用那个迭代器,现在调用算法很干净,但我不得不为迭代器编写很多样板代码。也许这只是我对如何使用算法和迭代器的误解......实际上这只是我有时遇到的一般问题的一个例子:我有一系列基于简单模式计算的数字而且我想要一个迭代器,当dereferenced返回该序列中的相应数字时。当序列存储在容器中时,我只使用容器提供的迭代器,但我也想这样做,当没有存储值的容器时也是如此。我当然可以尝试编写自己的通用迭代器来完成这项工作,但是标准库中是否存在可以帮助的东西?
对我而言,感觉有点奇怪,我可以使用lambda欺骗accumulate
来计算内在产品,但直接使用inner_product
我必须做一些额外的事情(要么预先计算权力)并将它们存储在一个容器中,或者写一个迭代器,即一个单独的class
)。
tl; dr:有没有简单的方法可以减少上面pow_iterator
的样板?
更普遍(但可能过于宽泛)的问题:它是否可以&#34;确定&#34;使用迭代器来处理未存储在容器中的值序列,但只有在解除引用迭代器时才计算?有没有&#34; C ++方式&#34;实施它?
答案 0 :(得分:1)
正如理查德·霍奇斯在评论中写道,你可以看看boost::iterator
。或者,有range-v3
。如果你选择加强,有几种可能的方法。以下显示如何使用boost::iterator::counting_iterator
和boost::iterator::transform_iterator
(C ++ 11):
#include <iostream>
#include <cmath>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/transform_iterator.hpp>
int main() {
const std::size_t base = 2;
auto make_it = [](std::size_t i) {
return boost::make_transform_iterator(
boost::make_counting_iterator(i),
[](std::size_t j){return std::pow(base, j);});};
for(auto b = make_it(0); b != make_it(10); ++b)
std::cout << *b << std::endl;
}
这是输出:
$ ./a.out
1
2
4
8
16
32
64
128
256
512