[英]How can I avoid using a const_cast with std::vector::erase() in C++?
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. 显然, std::vector::erase()
不能使用const_iterator
,但std::find()
需要一个。 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. 在将它提供给std::vector::erase()
,我可以抛弃std::find()
返回的迭代器的const
,但Effective C ++教会我怀疑const_cast
。
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. 我无法相信从向量中移除元素这一常见的东西应该需要类型体操。 :) :)
I suggest you change or overload your _iterator_for_node()
function to accept a non-const reference to the list. 我建议您更改或重载_iterator_for_node()
函数以接受对列表的非const引用。 The reason std::find
returns a const_iterator
is because the list itself is const
, and therefore begin()
and end()
return const_iterator
s. std::find
返回const_iterator
的原因是因为列表本身是const
,因此begin()
和end()
返回const_iterator
。
As an aside, const_cast<>
won't actually convert a const_iterator
to an iterator
as the 'const' is just part of the name, not a CV-qualifier. const_cast<>
一句, const_cast<>
实际上不会将const_iterator
转换为iterator
因为'const'只是名称的一部分,而不是CV限定符。
Also, you're not technically supposed to prefix names with an underscore, as this is reserved for implementations. 此外,从技术上讲,您不应该使用下划线为名称添加前缀,因为这是为实现保留的。 (it will generally work in practice) (它通常会在实践中工作)
Aside from my direct modification of the code , here's an idea: 除了我对代码的直接修改 ,这里有一个想法:
Instead of a member function _iterator_for_node
which 而不是成员函数_iterator_for_node
I suggest creating the following static (global/namespace) function instead: 我建议改为创建以下静态(全局/命名空间)函数:
template<class It, class T>
It checked_find(It begin, It end, const T& node)
{
It iter = std::find(begin, end, node);
if (iter != end)
return iter;
throw NoSuchNodeException();
}
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 :) 它将适用于任何迭代器类型(包括非STL,输入流迭代器,仅转发,const, 反向迭代器......你的名字),它不需要显式区分const /非const版本:)
a working version of your code sample would just read 您的代码示例的工作版本只会读取
template<class T>
class AdjacencyList {
std::vector<T> _nodes;
public:
void delete_node(const T& node)
{ _nodes.erase(checked_find(_nodes.begin(), _nodes.end(), node)); }
};
Note the code reduction. 请注意代码缩减。 Always the good sign 总是好兆头
Cheers 干杯
There seems to be quite some confusion between const elements, and const iterators in your code. const元素和代码中的const迭代器之间似乎存在很多混淆。
Without looking in to the use case, I propose the following 'fix' to make things compile: 在没有查看用例的情况下,我建议使用以下“修复”来编译:
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
struct NoSuchNodeException {};
template<class T>
class AdjacencyList {
std::vector<T> _nodes;
public:
void delete_node(const T&);
protected:
typename std::vector<T>::iterator _iterator_for_node(std::vector<T>&, const T&);
typename std::vector<T>::const_iterator _iterator_for_node(const std::vector<T>&, const T&) const;
};
template<class T>
void AdjacencyList<T>::delete_node(const T& node) {
_nodes.erase(_iterator_for_node(_nodes, node));
}
template<class T>
typename std::vector<T>::iterator AdjacencyList<T>::_iterator_for_node(std::vector<T>& list, const T& node)
{
typename std::vector<T>::iterator iter = std::find(list.begin(), list.end(), node);
if (iter != list.end())
return iter;
throw NoSuchNodeException();
}
template<class T>
typename std::vector<T>::const_iterator AdjacencyList<T>::_iterator_for_node(const std::vector<T>& list, const T& node) const
{
typename std::vector<T>::const_iterator iter = std::find(list.begin(), list.end(), node);
if (iter != list.end())
return iter;
throw NoSuchNodeException();
}
int main()
{
AdjacencyList<int> test;
test.delete_node(5);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.