R zu
R zu

Reputation: 2074

Set iterator_bracket_proxy for boost::iterator_adapter

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

Answers (1)

O&#39;Neil
O&#39;Neil

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 of p[n] is an object convertible to the iterator's value_type, and p[n] = x is equivalent to *(p + n) = x (Note: This result object may be implemented as a proxy containing a copy of p+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 an operator[] that returns an lvalue in the derived iterator class; it will hide the one supplied by iterator_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

Related Questions