Reputation: 2074
I try to make a random access iterator It
.
The indexing operation of It
should return a Node
.
But it doesn't. How to make it do that?
Test:
#include <iostream>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/counting_iterator.hpp>
template<typename T>
class Node {
public:
explicit Node(const T index) : index_(index) {}
const T index_;
};
template<typename T>
class It
: public boost::iterator_adaptor<
It<T>, // Derived
boost::counting_iterator<T>, // Base
Node<T>, // Value
std::random_access_iterator_tag, // CategoryOrTraversal
Node<T>, // Reference
boost::use_default // Difference
> {
protected:
using self_type = It<T>;
using node_type = Node<T>;
public:
explicit It(const T& x) : self_type::iterator_adaptor_(x){}
Node<T> operator*() const {
// Dereferencing gives a index instead of a reference.
auto& base_iterator = this->base_reference();
return Node<T>(*base_iterator);
}
protected:
friend class boost::iterator_core_access;
};
int main() {
It<int> a(10);
std::cout << (*a).index_ << "\n";
// a[4] is a
// class boost::iterators::detail
// ::operator_brackets_proxy<It<int> >
// instead of a Node<int>.
std::cout << a[4].index_ << "\n";
}
Error:
error: ‘boost::iterators::detail
::operator_brackets_result<It<int>, Node<int>, Node<int> >::type
{aka class boost::iterators::detail
::operator_brackets_proxy<It<int> >}’
has no member named ‘index_’
std::cout << a[4].index_ << "\n";
^~~~~~
Upvotes: 0
Views: 84
Reputation: 3849
See documentation operator[]
Writable iterators built with iterator_facade implement the semantics required by the preferred resolution to issue 299 and adopted by proposal n1550:
(1)the result ofp[n]
is an object convertible to the iterator'svalue_type
, andp[n] = x
is equivalent to*(p + n) = x
(Note: This result object may be implemented as a proxy containing a copy ofp+n
). This approach will work properly for any random-access iterator regardless of the other details of its implementation.
(2)A user who knows more about the implementation of her iterator is free to implement anoperator[]
that returns an lvalue in the derived iterator class; it will hide the one supplied byiterator_facade
from clients of her iterator.
As of (1), you may write:
std::cout << static_cast<Node<int>>(a[4]).index_ << "\n";
Or (2) implement operator[]
:
Node<T> operator[](std::ptrdiff_t n) const {
return *std::next(*this,n);
}
std::cout << a[4].index_ << "\n";
or write instead:
std::cout << std::next(a,4)->index_ << "\n";
std::cout << (a+4)->index_ << "\n";
Upvotes: 1