繁体   English   中英

编译器不能在Vector_const_iterator和Vector_iterator之间“转换”,即使两者的方法都可用

[英]Compiler can't “convert” between Vector_const_iterator and Vector_iterator, even though methods for both are available

我正在尝试围绕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_iterator的方法。 为什么编译器不能在它们之间进行选择?


在这个问题中隐含的是,这是否是一个很好的策略来隐藏调用者的细节(因为他们仍然必须处理这些std :: vector类型),我希望能解决这个问题的答案。

charVec::reverse_iterator next_coef = poly.h2l_begin();

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

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

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则不允许。

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

其次,请注意,编译器永远不会在基于返回类型的函数之间选择 (除了可转换operator T() )。 如果你有一个非const poly存储在const_reverse_iterator ,你仍然会调用reverse_iterator h2l_begin() reverse_iterator只会转换为const_reverse_iterator


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

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

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

最后,我写了backwards_tbackwards函数,它接受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

这很好。

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)

改变这个:

charVec::reverse_iterator next_coef;

对此:

charVec::const_reverse_iterator next_coef;

你看: poly是对gf255_poly对象的const引用,意思是对poly.h2l_begin();的请求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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM