为了乐趣和利润™,我正在用 C++ 编写一个 trie 类(使用 C++11 标准。)
我trie<T>
有一个迭代器,trie<T>::iterator
. (它们实际上都是函数 const_iterator
式 s,因为您不能修改 trie 的value_type
。)迭代器的类声明部分看起来像这样:
template<typename T>
class trie<T>::iterator : public std::iterator<std::bidirectional_iterator_tag, T> {
friend class trie<T>;
struct state {
state(const trie<T>* const node, const typename std::vector<std::pair<typename T::value_type, std::unique_ptr<trie<T>>>>::const_iterator& node_map_it ) :
node{node}, node_map_it{node_map_it} {}
// This pointer is to const data:
const trie<T>* node;
typename std::vector<std::pair<typename T::value_type, std::unique_ptr<trie<T>>>>::const_iterator node_map_it;
};
public:
typedef const T value_type;
iterator() =default;
iterator(const trie<T>* node) {
parents.emplace(node, node->children.cbegin());
// ...
}
// ...
private:
std::stack<state> parents;
// ...
};
请注意,node
指针已声明const
。这是因为(在我看来)迭代器不应该修改它指向的节点;它只是一个迭代器。
现在,在我的主trie<T>
类的其他地方,我有一个具有通用 STL 签名的擦除函数——它需要一个iterator
to 数据来擦除(并返回一个iterator
到下一个对象)。
template<typename T>
typename trie<T>::iterator trie<T>::erase(const_iterator it)
{
// ...
// Cannot modify a const object!
it.parents.top().node->is_leaf = false;
// ...
}
编译器抱怨,因为node
指针是只读的!该erase
函数肯定应该修改迭代器指向的 trie,即使迭代器不应该这样做。
所以,我有两个问题:
- 的构造函数应该
iterator
是公开的吗?trie<T>
有必要的begin()
和end()
成员,当然trie<T>::iterator
和trie<T>
是共同的朋友,但我不知道公约是什么。将它们设为私有将解决我对const
从迭代器的构造函数中删除“承诺”的许多焦虑。 const
关于迭代器及其node
指针的正确语义/约定是什么? 从来没有人向我解释过这一点,我在网上找不到任何教程或文章。这可能是更重要的问题,但它确实需要大量的计划和适当的实施。我想它可以通过实现 1 来规避,但这是事情的原理!