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

标签 c++ visual-studio-2008 stdvector const-iterator reverse-iterator

我正在尝试围绕 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_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 ,您已 promise 不修改。然后你使用可以修改它的类型对其进行迭代。所以你得到一个类型错误。

其次,顺便说一句,请注意编译器从不根据返回类型在函数之间进行选择(可以说转换 operator T() 除外)。如果你有一个非常量 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

这很好。

关于c++ - 编译器不能在 Vector_const_iterator 和 Vector_iterator 之间使用 "convert",即使两者的方法都可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39399592/

相关文章:

c++ - 使用 reinterpret_cast 将 char* 转换为 vector<byte>

visual-studio-2008 - 调试命令(step over/into)导致未处理的异常

c++ - 检查游戏是否结束的函数

c++ - 如何从 C++ 代码中检索 QML 的 TextField 中的文本?

visual-studio-2008 - nHibernate 和 sqlite 映射

c++ - 如何在 while 循环中重新初始化 vector ?

c++ - 如何使用为构造函数指定的大小来初始化 C++ 中的数组?

C++ vector 下限和上限检查

C++ Gdiplus 单色像素值

c++ - Visual Studio 预处理器仅在设置了/P 时才有效