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. :)
I suggest you change or overload your _iterator_for_node()
function to accept a non-const reference to the list. The reason std::find
returns a const_iterator
is because the list itself is const
, and therefore begin()
and end()
return const_iterator
s.
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.
Also, you're not technically supposed to prefix names with an underscore, as this is reserved for implementations. (it will generally work in practice)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With