【问题标题】:How to use two functions, one returning iterator, the other returning const_iterator如何使用两个函数,一个返回迭代器,另一个返回 const_iterator
【发布时间】:2011-10-24 10:38:29
【问题描述】:

所以我有一个叫做 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

【问题讨论】:

  • 在您调用 myTree.find 的地方,btree 迭代器的 const 和非 const 版本是否可见?你能把整个文件贴出来吗?
  • 用源代码链接编辑问题

标签: c++ iterator compiler-errors constants


【解决方案1】:

所有标准容器都实现了非 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) { /* .... */ }
};

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

【讨论】:

  • 谢谢!那行得通,我真的认为 C++ 会以某种方式调用正确的 find 版本,但我想情况并非如此
  • 不。我知道“重载解决方案”出现在 backtrack 并在 C++ 中继续尝试的唯一地方是著名的 SFINAE 规则(实际上,它并没有真正忽略重载:它忽略了失败的模板实例化)
【解决方案2】:

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

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

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

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

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

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

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

【讨论】:

  • 谢谢你,我用你提到的从迭代器到 const_iterator 的转换来修复它
  • @Arvin 我不清楚 在我的测试文件中是否意味着您正在尝试测试 find const 重载或 const_iterator 或只是容器一般。
  • “在我的测试文件中”是指在一个单独的 cpp 文件中的主函数内部,该文件测试我的 btree 类实现。我实际上是在测试容器并偶然发现了这个问题
猜你喜欢
  • 2010-09-23
  • 1970-01-01
  • 1970-01-01
  • 2022-08-13
  • 1970-01-01
  • 2010-09-15
  • 2011-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多