How to use two functions, one returning an iterator, the other returning a const_iterator

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 an error

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

Which, obviously, means that find always uses a version of the iterator (not const ). I know that C ++ should automatically call the const_iterator version - if I did everything right. So the question is, what can I do wrong?

Iteration classes:

class btree_iterator and class const_btree_iterator , which is only a copied copy of btree_iterator with names changed

Here is the complete 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

+7
source share
2 answers

All standard containers implement the conversion of non-constant constant iterators (as specified in the requirements for the container concept ):

The type of iterator used to iterate through container elements. Iterator value type is expected to be container value type. Conversion from iterator type to const iterator type must exist .

You need a conversion constructor like this:

 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 also introduced an assignment operator, but I believe that it is redundant

+9
source

The important thing here is that overload resolution is only done based on the arguments of the function, 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 the overload will be collected whenever the static type of the object or the reference to which the method is called are constant.

If you want to force send a constant overload, you can get a link to a constant and then call this link:

 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. The reason is that const and non-const overloads should have the same semantics, and therefore the behavior should be the same.

Also note that in standard containers there is an implicit conversion from iterator to const iterator to support the use of const_iterator directly in containers that do not contain constants. You must do the same, that is, if you provide an implicit conversion from iterator to const_iterator , then you can simply write:

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

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

+5
source

All Articles