所以我有一个名为find的函数,它有两个版本:
template <typename T>
typename btree<T>::iterator btree<T>::find(const T& elem)
{
//Implementation
}
另一个是const_iterator版本:
template <typename T>
typename btree<T>::const_iterator btree<T>::find(const T& elem) const
{
//Implementation
}
在我的测试文件中
btree<char>::iterator it = myTree.find('M');
一切正常,但是当我使用const_iterator版本时:
btree<char>::const_iterator it = myTree.find('M');
它给了我错误
错误:从'btree_iterator'转换为非标量类型'const_btree_iterator'请求
这显然意味着find只使用迭代器(非const
)版本。我知道C ++应该自动调用const_iterator
版本 - 如果我做的一切正确的话。所以问题是,我可能做错了什么?
迭代器类是:
class btree_iterator
和class const_btree_iterator
这只是btree_iterator
的复制粘贴,其名称已更改
以下是完整的源代码:
btree_iterator.h(包括const_btree_iterator)http://pastebin.com/zQnj9DxA
btree.h http://pastebin.com/9U5AXmtV
btree.tem http://pastebin.com/U9uV3uXj
答案 0 :(得分:9)
所有标准容器都实现了非const到const迭代器的转换(如specified in the requirements for the Container concept):
用于迭代容器元素的迭代器类型。迭代器的值类型应该是容器的值类型。 必须存在从迭代器类型到const迭代器类型的转换。
你需要像这样的转换构造函数:
class btree_iterator;
class const_btree_iterator
{
// ....
public:
const_btree_iterator(const btree_iterator& rhs) { /* .... */ }
//optionally: const_btree_iterator& operator=(const btree_iterator& rhs) { /* .... */ }
};
我也投入了赋值运算符,但我认为它是多余的
答案 1 :(得分:5)
这里重要的一点是,只根据函数的参数而不是结果执行重载决策。在您的特定情况下,您有两个不同的重载,区别在于隐式this
在其中一个中是常量,只要调用该方法的对象或引用的静态类型是常量,就会获取重载
如果要强制调度到常量重载,可以获取const引用,然后调用该引用:
btree<char> const & r = myTree;
btree<char>::const_iterator it = r.find('M');
您应该在实际代码中避免使用此构造,即使您将其用于测试目的。原因是const和非const重载应该具有相同的语义,因此行为应该是相同的。
另请注意,在标准容器中,存在从iterator
到const iterator
的隐式转换,以支持在非const容器上直接使用const_iterator
。您应该这样做,也就是说,如果您提供从iterator
到const_iterator
的隐式转换,那么您可以写一下:
btree<char>::const_iterator it = myTree.find('M');
...它会起作用(不会测试find
方法,但会允许您验证const_iterator
行为)