2014/1/9 Sebastian Pfützner <s.pfuetzner@onlinehome.de>
Hello,

the following code does not compile with the last line in main(). The error message is

main.cpp: In function 'int main()':
main.cpp:37:8: error: 'boost::detail::operator_brackets_result<It, S, S&>::type' has no member named 'i'
  it[3].i = 0;
        ^

What could be the problem?


#include <boost/iterator/iterator_facade.hpp>

struct S
{
        int i;
        float f;
};

class It :
        public boost::iterator_facade<It, S, boost::random_access_traversal_tag>
{
private:
        friend class boost::iterator_core_access;

        static S s;

        reference dereference() const
        { return s; }

        bool equal(It const&) const
        { return true; }

        void increment() {}
        void decrement() {}
        void advance(difference_type n) {}

        difference_type distance_to(It const&) const
        { return 0; }
};

int main()
{
        It it;
        (*(it + 3)).i = 0;
        S& s = it[3];
        s.i = 0;
        it[3].i = 0;
}

Hello,

In your case, it[3] returns a boost::detail::operator_brackets_proxy<It> instead of S& you expect:

    // A proxy return type for operator[], needed to deal with
    // iterators that may invalidate referents upon destruction.
    // Consider the temporary iterator in *(a + n)
    template <class Iterator>
    class operator_brackets_proxy;

As the comment sais, it[3] won't return a reference directly "to deal with
    // iterators that may invalidate referents upon destruction.
    // Consider the temporary iterator in *(a + n)". I don't know in what situations that can happen.

I don't see a clean way to force it[3]  to return a real reference. Can anyone comment on this?

That said, here's a hack for you: right after the definition of struct S insert this code:

class It;

namespace boost { namespace detail {
template <> struct operator_brackets_result<It,S,S&>
{ typedef S& type; };
}}

(Your code won't link as it is, buth that's irrelevent here)
HTH
Kris