如何使用两个函数,一个返回iterator,另一个返回const_iterator

发布于 2024-12-11 20:11:55 字数 1329 浏览 0 评论 0原文

所以我有一个名为 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_iteratorclass 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

So I have a function called find, which has two versions:

template <typename T> 
typename btree<T>::iterator btree<T>::find(const T& elem)
{
    //Implementation
}

and the other is the const_iterator version:

template <typename T> 
typename btree<T>::const_iterator btree<T>::find(const T& elem) const
{
    //Implementation
}

In my test file when I do

btree<char>::iterator it = myTree.find('M');

Everything works fine, however when I use the const_iterator version:

btree<char>::const_iterator it = myTree.find('M');

It gives me the error

error: conversion from 'btree_iterator' to non-scalar type 'const_btree_iterator' requested

Which obviously means that find is only ever using the iterator (non const) version. I know that C++ is supposed to call the const_iterator version automatically - if I had done everything right. So the question is, what might I be doing wrong?

The iterator classes are:

class btree_iterator and class const_btree_iterator which is just a copy paste of btree_iterator with the names changed

Here are the full source code:
btree_iterator.h (includes const_btree_iterator) http://pastebin.com/zQnj9DxA
btree.h http://pastebin.com/9U5AXmtV
btree.tem http://pastebin.com/U9uV3uXj

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

花开半夏魅人心 2024-12-18 20:11:55

所有标准容器都实现了非常量迭代器到常量迭代器的转换(如容器概念的要求中指定的):

用于迭代容器元素的迭代器类型。迭代器的值类型应为容器的值类型。 必须存在从迭代器类型到 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) { /* .... */ }
};

我也加入了赋值运算符,但我认为它是多余的

All the standard containers implement conversion of non-const to const iterators (as specified in the requirements for the Container concept):

The type of iterator used to iterate through a container's elements. The iterator's value type is expected to be the container's value type. A conversion from the iterator type to the const iterator type must exist.

You need conversion constructor like so:

class btree_iterator;
class const_btree_iterator
{
       // ....
       public:
              const_btree_iterator(const btree_iterator& rhs) { /* .... */ }
//optionally: const_btree_iterator& operator=(const btree_iterator& rhs) { /* .... */ }
};

I threw in the assignment operator too but I suppose it is redundant

骑趴 2024-12-18 20:11:55

这里重要的一点是,重载决策仅基于函数的参数而不是结果来执行。在您的特定情况下,您有两个不同的重载,区别在于隐式 this 在其中一个重载中是常量,只要该方法所在的对象或引用的静态类型,就会拾取该重载称为常数。

如果您想强制分派常量重载,您可以获取一个 const 引用,然后调用该引用:

btree<char> const & r = myTree;
btree<char>::const_iterator it = r.find('M');

您应该在实际代码中避免使用此构造,即使您将其用于测试目的。原因是 const 和非常量重载应该具有相同的语义,因此行为应该相同。

另请注意,在标准容器中,存在从 iteratorconst iterator 的隐式转换,以支持直接在非常量容器上使用 const_iterator。你应该做同样的事情,也就是说,如果你提供从 iteratorconst_iterator 的隐式转换,那么你可以只写:

btree<char>::const_iterator it = myTree.find('M');

... 它会工作(不会测试 find 方法,但将允许您验证 const_iterator 行为)

The important bit here is that overload resolution is performed based only on the arguments to the function and not the result. In your particular case you have two different overloads and the difference is that the implicit this is constant in one of them, that overload will be picked up whenever static type of the object or reference on which the method is called is constant.

If you want to force dispatch to the constant overload, you can obtain a const reference and then call on that reference:

btree<char> const & r = myTree;
btree<char>::const_iterator it = r.find('M');

You should avoid this construct in real code, even if you use it for testing purposes. The reason is that the const and non-const overloads should have the same semantics and thus the behavior should be the same.

Also note that in standard containers, there is an implicit conversion from iterator to const iterator to support using const_iterators directly on non-const containers. You should do the same, that is, if you provide an implicit conversion from iterator to const_iterator, then you can just write:

btree<char>::const_iterator it = myTree.find('M');

... and it will work (will not test the find method, but will allow you to verify the const_iterator behavior)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文