Implementing a binary search tree, I need to write a iterator and a constant_iterator.
My iterator has to be templated on nodeType and pairType, as I did here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
template <typename nodeType, typename pairType >
struct _iterator {
nodeType* current;
//public:
using value_type = pairType;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
using reference = value_type&;
using pointer = value_type *;
explicit _iterator(nodeType* pn) noexcept: current{pn} {}
//implementation of all the other functions
and in the definition of my binary search tree class I have the following typedefs:
1 2 3
using iterator = _iterator<node_type,pair_type>;
using constant_iterator = _iterator<node_type,const pair_type>;
Actually, nodeType=Node<pair_type>, since the Node is templated on pair_type. So I decided to template my iterator on the pair_type only, but now it doesn't work anymore when I want to use in my code the constant version, which is "typedef"ed in this way:
1 2 3
using iterator = _iterator<pair_type>;
using constant_iterator = _iterator<const pair_type>; //this creates problem
because when I use the constant version he can't construct the iterator, for instance in the cbegin function call. Why do I have problems if I give just one template? The problems appear to be in the constructor, but I can't understand how.
You did not provide enough code to reproduce the problem. Please provide a minimal compilable expample.
One possible problem might be that with constant members no copy constructor will be generated by the compiler. In that case you need to provide your own.
The problem is in bst line 22/45: You have a pointer to Node<pair_type>. The constant_iterator requires Node<const pair_type> which are different types.
Uhm, the only necessary thing is to have a constant iterator.
Actually, your comment enlightened me (maybe).
Since a constant iterator must point to something constant, and my iterator is pointing to a Node, now I think that I should impose that the Node is constant, rather than the pair itself as I was doing. In practice, what I want to be constant is Node<T>, where T will be a std::pair with key and value
So if you think to a constant iterator for your bst, you would like to have constantness only for each std::pair, and not for children?
This sounds strange to me, because if I can still modify something (for instance left, right, parent), I wouldn't say that the iterator is pointing to something constant.
I do not wish to be controversial, my question is just pure curiosity :-)
Anyway, I think I got your workaround. Now I'll try to follow the flow of the code to check it more carefully.
In that case neither the children nor the parent are const. Only the pointer to them.
This sounds strange to me, because if I can still modify something (for instance left, right, parent), I wouldn't say that the iterator is pointing to something constant.
It's not that strange. The node is for internal while the data for external use. So that the user of your class bst never gets in touch with the node.
But it entirely depends on what you want to achieve.
The standard container behave like that. I.e. you can use const_iterator for removing/adding etc. The only restriction is that you get const data for reference (operator->) or dereference (operator*)