编译器不能在 Vector_const_iterator 和 Vector_iterator 之间 "convert",即使两者的方法都可用

Compiler can't "convert" between Vector_const_iterator and Vector_iterator, even though methods for both are available

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

使用 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>'

我不明白这条消息 - 我提供了 return 迭代器和 const_iterators 的方法。为什么编译器不能在它们之间进行选择?


这个问题中隐含的是,这是否是一个很好的策略,可以完全隐藏调用者的详细信息(因为他们仍然必须处理这些 std::vector 类型),我希望得到同样解决的答案这个。

poly 是一个 const 对象,所以 h2l_begin() 将 return 变成 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)
charVec::reverse_iterator next_coef = poly.h2l_begin();

next_coef 是一个 reverse_iteratorh2l_begin() return 是什么意思?

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

有两个重载。只有一个有效,因为polyconst,就是这个:

charVec::const_reverse_iterator h2l_begin() const { return p.rbegin(); };

所以poly.h2l_begin()return一个charVec::const_reverse_iterator.

charVec::const_reverse_iterator 无法转换为 charVec::reverse_iterator,因为 charVec::const_reverse_iterator 允许您修改被迭代的内容,而 charVec::reverse_iterator 则不允许。

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

其次,顺便说一句,请注意编译器从不在基于return类型的函数之间进行选择(转换operator T()除外)。如果您有一个非常量 poly 将其存储在 const_reverse_iterator 中,您仍然会调用 reverse_iterator h2l_begin()reverse_iterator 只会转换为 const_reverse_iterator.


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

其次,我会写一个 range_t<Iterator> 来存储一系列迭代器并公开 beginend 并且有条件地(基于 [=41 的随机访问性) =] operator[]size 等。还有 remove_front(size_t)front() 以及 empty 和 ...

然后我会写 array_view<T>:range_it<T*> 表示一系列连续的 Ts,带有来自带有 T* C::data() 方法的容器的隐式 ctors,原始 C 数组和 T*, size_t.

最后,我会编写 backwards_tbackwards 函数,它接受一个 range_t<Iterator> 和 return 一个 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

这很好。

改变这个:

charVec::reverse_iterator next_coef;

对此:

charVec::const_reverse_iterator next_coef;

您看到:poly 是对 gf255_poly 对象的 const 引用,这意味着对 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