如何避免在 C++ 中使用 const_cast 和 std::vector::erase() ?
我有一个这样的类:
template<class T>
class AdjacencyList {
public:
void delete_node(const T&);
protected:
const typename std::vector<T>::const_iterator _iterator_for_node(
const std::vector<T>&, const T&
);
};
template<class T>
void AdjacencyList<T>::delete_node(const T& node) {
_nodes.erase(_iterator_for_node(_nodes, node));
}
template<class T>
const typename std::vector<T>::const_iterator AdjacencyList<T>::_iterator_for_node(
const std::vector<T>& list, const T& node
) {
typename std::vector<T>::const_iterator iter =
std::find(list.begin(), list.end(), node);
if (iter != list.end())
return iter;
throw NoSuchNodeException();
}
显然,std::vector::erase()
不能采用const_iterator
,但是std::find()
> 需要一个。当将 std::find()
返回的迭代器提供给 std::vector::erase()< 时,我可以抛弃它的
const
-ness /code>,但是 Effective C++ 教会我尊重const_cast
带着怀疑。
还有其他方法可以做到这一点吗?我不敢相信像从向量中删除元素这样常见的事情竟然需要类型体操。 :)
I have a class like this:
template<class T>
class AdjacencyList {
public:
void delete_node(const T&);
protected:
const typename std::vector<T>::const_iterator _iterator_for_node(
const std::vector<T>&, const T&
);
};
template<class T>
void AdjacencyList<T>::delete_node(const T& node) {
_nodes.erase(_iterator_for_node(_nodes, node));
}
template<class T>
const typename std::vector<T>::const_iterator AdjacencyList<T>::_iterator_for_node(
const std::vector<T>& list, const T& node
) {
typename std::vector<T>::const_iterator iter =
std::find(list.begin(), list.end(), node);
if (iter != list.end())
return iter;
throw NoSuchNodeException();
}
Apparently, std::vector::erase()
cannot take a const_iterator
, but std::find()
requires one. I could cast away the const
-ness of the iterator returned by std::find()
when feeding it to std::vector::erase()
, but Effective C++ taught me to regard const_cast
with suspicion.
Is there another way to do this? I can't believe that something as common as removing an element from a vector should require type gymnastics. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我建议您更改或重载
_iterator_for_node()
函数以接受对列表的非常量引用。std::find
返回const_iterator
的原因是列表本身是const
,因此begin()
和end()
返回const_iterator
。顺便说一句,
const_cast<>
实际上不会将const_iterator
转换为iterator
,因为“const”只是名称的一部分,不是 CV 限定符。另外,从技术上讲,您不应该在名称前添加下划线,因为这是为实现保留的。 (实践中一般都会起作用)
I suggest you change or overload your
_iterator_for_node()
function to accept a non-const reference to the list. The reasonstd::find
returns aconst_iterator
is because the list itself isconst
, and thereforebegin()
andend()
returnconst_iterator
s.As an aside,
const_cast<>
won't actually convert aconst_iterator
to aniterator
as the 'const' is just part of the name, not a CV-qualifier.Also, you're not technically supposed to prefix names with an underscore, as this is reserved for implementations. (it will generally work in practice)
除了我的直接修改代码,这里有一个想法:
成员函数
_iterator_for_node
我建议创建以下静态(全局/命名空间)函数:
它将适用于任何迭代器类型(包括非 STL、输入流迭代器、仅向前,const,反向迭代器...你能想到的)并且它不需要const/非const版本之间的显式区别:)
有了它,
代码示例的工作版本将只读取
注意代码的减少。永远是好兆头
干杯
Aside from my direct modification of the code, here's an idea:
Instead of a member function
_iterator_for_node
whichI suggest creating the following static (global/namespace) function instead:
It will work with any iterator type (including non-STL, input stream iterators, forward only, const, reverse iterators... you name it) and it doesn't require explicit distinction between const/non const versions :)
With it,
a working version of your code sample would just read
Note the code reduction. Always the good sign
Cheers
代码中的 const 元素和 const 迭代器之间似乎存在相当大的混淆。
在不查看用例的情况下,我建议使用以下“修复”来进行编译:
There seems to be quite some confusion between const elements, and const iterators in your code.
Without looking in to the use case, I propose the following 'fix' to make things compile: