编译器不能在 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_iterator
。 h2l_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(); };
有两个重载。只有一个有效,因为poly
是const
,就是这个:
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
则不允许。
总之,因为poly
是const
,您已经承诺不修改了。然后你使用可以修改它的类型对其进行迭代。所以你得到一个类型错误。
其次,顺便说一句,请注意编译器从不在基于return类型的函数之间进行选择(转换operator T()
除外)。如果您有一个非常量 poly
将其存储在 const_reverse_iterator
中,您仍然会调用 reverse_iterator h2l_begin()
。 reverse_iterator
只会转换为 const_reverse_iterator
.
首先要做的是升级到 C++11。这是 2016 年。
其次,我会写一个 range_t<Iterator>
来存储一系列迭代器并公开 begin
和 end
并且有条件地(基于 [=41 的随机访问性) =] 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_t
和 backwards
函数,它接受一个 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
我正在尝试围绕 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_iterator
。 h2l_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(); };
有两个重载。只有一个有效,因为poly
是const
,就是这个:
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
则不允许。
总之,因为poly
是const
,您已经承诺不修改了。然后你使用可以修改它的类型对其进行迭代。所以你得到一个类型错误。
其次,顺便说一句,请注意编译器从不在基于return类型的函数之间进行选择(转换operator T()
除外)。如果您有一个非常量 poly
将其存储在 const_reverse_iterator
中,您仍然会调用 reverse_iterator h2l_begin()
。 reverse_iterator
只会转换为 const_reverse_iterator
.
首先要做的是升级到 C++11。这是 2016 年。
其次,我会写一个 range_t<Iterator>
来存储一系列迭代器并公开 begin
和 end
并且有条件地(基于 [=41 的随机访问性) =] 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_t
和 backwards
函数,它接受一个 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