我试图围绕std :: vector创建一个小包装类来表示多项式的系数。调用者需要能够遍历系数,但我不想暴露底层实现。
使用here,here和其他地方描述的模式,我试图传递迭代器,如下所示:
typedef std::vector<unsigned char> charVec;
class gf255_poly
{
public:
// Constructors and Polynomial-y Functions
// ...
// Iterators to go from high to low degree
charVec::const_reverse_iterator h2l_begin() const { return p.rbegin(); };
charVec::const_reverse_iterator h2l_end() const { return p.rend(); };
charVec::reverse_iterator h2l_begin() { return p.rbegin(); };
charVec::reverse_iterator h2l_end() { return p.rend(); };
// Iterators to go from low to high degree
charVec::const_iterator l2h_begin() const { return p.begin(); };
charVec::const_iterator l2h_end() const { return p.end(); };
charVec::iterator l2h_begin() { return p.begin(); };
charVec::iterator l2h_end() { return p.end(); };
protected:
std::vector<unsigned char> p;
};
然后将这些gf255_poly对象用于以下方法:
// Performs polynomial evaluation in GF(2^8)
unsigned char gf255_poly_eval(const gf255_poly &poly, unsigned char x) const
{
unsigned char fx = poly.coefHigh(); // Initialize with coef of highest degree term
// Use Horner's method with consecutively factored terms:
// x^3 + 2x^2 + 3x + 4 -> (((1x + 2)x + 3)x + 4)
charVec::reverse_iterator next_coef;
for (next_coef = poly.h2l_begin(); next_coef != poly.h2l_end(); next_coef++)
fx = gf255_mul(fx, x) ^ *next_coef; // Recall ^ is addition in GF 2^8
return fx;
}
虽然看起来很简单但是这些类型出现了问题。 Visual Studio在for循环中给出了这个错误,我似乎无法解决这个问题:
error C2664: 'std::_Revranit<_RanIt,_Base>::_Revranit(_RanIt)' : cannot convert parameter 1 from 'std::_Vector_const_iterator<_Ty,_Alloc>' to 'std::_Vector_iterator<_Ty,_Alloc>'
我不理解这条消息 - 我提供了返回迭代器和const_iterator的方法。为什么编译器不能在它们之间做出选择?
在这个问题中隐含的是,这是否是一个很好的策略来隐藏调用者的详细信息(因为他们仍然需要处理这些std :: vector类型),我希望能够解决这个问题的答案。< / p>
答案 0 :(得分:2)
charVec::reverse_iterator next_coef = poly.h2l_begin();
next_coef
是reverse_iterator
。 h2l_begin()
返回什么?
好吧,poly
是:
const gf255_poly &poly
a const gf255_poly
。那么让我们来看看h2l_begin()
:
charVec::const_reverse_iterator h2l_begin() const { return p.rbegin(); };
charVec::reverse_iterator h2l_begin() { return p.rbegin(); };
有两个重载。只有一个有效,因为poly
是const
,就是这个:
charVec::const_reverse_iterator h2l_begin() const { return p.rbegin(); };
所以poly.h2l_begin()
会返回charVec::const_reverse_iterator
。
charVec::const_reverse_iterator
无法转换为charVec::reverse_iterator
,因为charVec::const_reverse_iterator
允许您修改正在迭代的内容,而charVec::reverse_iterator
则不会。{/ p>
简而言之,因为poly
是const
,您承诺不会修改它。然后使用可以修改它的类型对其进行迭代。所以你得到一个类型错误。
其次,请注意编译器永远不会在基于返回类型的函数之间选择(转换operator T()
除外)。如果您在poly
中存储了非常量const_reverse_iterator
,则仍然可以调用reverse_iterator h2l_begin()
。 reverse_iterator
只会转换为const_reverse_iterator
。
首先要做的是升级到C ++ 11。这是2016年。
其次,我写了一个range_t<Iterator>
来存储一系列迭代器并公开begin
和end
并且有条件地(基于{{1的随机访问权限) }} Iterator
,operator[]
等。size
和remove_front(size_t)
以及front()
和......
然后我写empty
代表一系列连续的array_view<T>:range_it<T*>
s,其中带有T
方法的容器的隐式ctors,原始C数组和{{ 1}}。
最后,我写了T* C::data()
和T*, size_t
函数,该函数需要backwards_t
并返回backwards
。
现在我的range_t<Iterator>
有以下内容:
range_t< reverse_iterator< Iterator > >
如果我们选择,我们可以为迭代器公开typedef(在C ++ 03中我们别无选择)。
在C ++ 11中,它看起来像:
gf255_poly
这很好。
答案 1 :(得分:1)
poly
是一个const对象,因此h2l_begin()
将返回一个const_reverse_iterator。您已将next_coef
声明为reverse_iterator
,并且无法将const迭代器分配给迭代器。将next_coef
更改为const_reverse_iterator
,或在for循环中使用auto声明它。
for (auto next_coef = poly.h2l_begin(); next_coef != poly.h2l_end(); ++next_coef)
答案 2 :(得分:0)
改变这个:
charVec::reverse_iterator next_coef;
到此:
charVec::const_reverse_iterator next_coef;
您会看到:poly
是对const
对象的gf255_poly
引用,这意味着对poly.h2l_begin();
的请求将更喜欢该const
限定版本的该函数在重载解决期间。
更好的是,使用auto
for (auto next_coef = poly.h2l_begin(); next_coef != poly.h2l_end(); next_coef++)
fx = gf255_mul(fx, x) ^ *next_coef; // Recall ^ is addition in GF 2^8
如果你仍然必须将迭代器保留在for循环初始化器之外,你可以将初始化移到外面:
auto next_coef = poly.h2l_begin()
for (; next_coef != poly.h2l_end(); next_coef++)
fx = gf255_mul(fx, x) ^ *next_coef; // Recall ^ is addition in GF 2^8