1

我正在尝试围绕 std::vector 创建一个小型包装类来表示多项式的系数。调用者需要能够遍历系数,但我不想公开底层实现。

使用此处此处和其他地方描述的模式,我尝试传递迭代器,如下所示:

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 类型),我将不胜感激也能解决这个问题的答案。

4

3 回答 3

3
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(); };

有两个重载。只有一个是有效的,因为polyis 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不允许。

简而言之,因为polyis const,您已经承诺不修改它。然后你使用可以修改它的类型对其进行迭代。所以你得到一个类型错误。

其次,顺便说一句,请注意编译器永远不会根据返回类型在函数之间进行选择(可以说是 conversion 除外operator T())。如果您将非常量poly存储在 a 中const_reverse_iterator,您仍然会调用reverse_iterator h2l_begin(). reverse_iterator只会转换const_reverse_iterator为.


首先要做的是升级到 C++11。这是2016年。

其次,我会编写一个range_t<Iterator>存储一系列迭代器并有条件地公开beginandend和 and (基于 , 等的随机访问性)Iterator operator[]以及sizeand remove_front(size_t)and front()and emptyand ...

然后我会写array_view<T>:range_it<T*>它表示一系列连续T的 s,其中包含来自容器的隐式 ctorsT* C::data()方法、原始 C 数组和T*, size_t.

最后,我会编写backwards_tbackwards函数,它接受 arange_t<Iterator>并返回 a 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

这很好。

于 2016-09-08T20:29:20.487 回答
1

poly是一个 const 对象,因此h2l_begin()将返回一个 const_reverse_iterator。您已声明next_coef为 a reverse_iterator,并且不能将 const 迭代器分配给迭代器。要么更改next_coef为 a const_reverse_iterator,要么在 for 循环中使用 auto 声明它。

for (auto next_coef = poly.h2l_begin(); next_coef != poly.h2l_end(); ++next_coef)
于 2016-09-08T20:28:52.873 回答
0

改变这个:

charVec::reverse_iterator next_coef;

对此:

charVec::const_reverse_iterator next_coef;

您会看到:polyconst对对象的引用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
于 2016-09-08T20:30:17.440 回答