我正在尝试围绕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_iterators的方法。编译器为什么不能在它们之间进行选择?
这个问题的隐含含义是,这是否是一个很好的策略,可以将所有细节都隐藏在调用方之外(因为它们仍然必须处理这些std::vector类型),我希望也能解决此问题。
最佳答案
charVec::reverse_iterator next_coef = poly.h2l_begin();
next_coef
是reverse_iterator
。 h2l_begin()
返回什么?好吧,
poly
是一个:const gf255_poly &poly
一个
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
则不能。简而言之,因为
poly
是const
,所以您已 promise 不会对其进行修改。然后您使用可以修改它的类型在它上面迭代。这样您会收到类型错误。其次,顺便提一句,请注意,编译器绝不会在基于返回类型的函数之间进行选择(可以说是转换
operator T()
除外)。如果您将非常量poly
存储在const_reverse_iterator
中,则仍将其称为reverse_iterator h2l_begin()
。 reverse_iterator
只会转换为const_reverse_iterator
。首先要做的是升级到C++ 11。这是2016年。
其次,我将编写一个
range_t<Iterator>
,其中存储了一系列迭代器,并有条件地公开begin
和end
(基于Iterator
operator[]
,size
等的随机访问性。还有remove_front(size_t)
和front()
以及empty
和...然后,我将编写
array_view<T>:range_it<T*>
,它表示一系列连续的T
,其中包含带有T* C::data()
方法,原始C数组和T*, size_t
的容器中的隐式ctor。最后,我将编写
backwards_t
和backwards
函数,该函数接受range_t<Iterator>
并返回range_t< reverse_iterator< Iterator > >
。现在我的
gf255_poly
具有以下内容:backwards_t< array_view< unsigned char > > h2l();
backwards_t< array_view< unsigned char const > > h2l() const;
array_view< unsigned char > l2h();
array_view< unsigned char const > l2h() const;
如果选择的话,我们可以为迭代器公开typedef(在C++ 03中,我们别无选择)。
在C++ 11中,它看起来像:
for (auto&& next_coef = poly.h2l())
fx = gf255_mul(fx, x) ^ next_coef; // Recall ^ is addition in GF 2^8
很好
关于c++ - 即使Vector_const_iterator和Vector_iterator之间的方法都可用,编译器也无法在它们之间 “convert”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39399592/