[iterator] error while accessing member of result of brackets-operator

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; } -- Sebastian Pfützner s.pfuetzner@onlinehome.de ICQ-ID: 39965036

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

On 09.01.2014 17:43, Krzysztof Czainski wrote:
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; }; }}
That works in the example. In my real code, /It/ is a template and I don't know how to specialize operator_brackets_result for each instantiation. Unfortunately, I can not change the algorithm, that accepts a random-access-iterator of a certain class and uses it like in the example. It is surprising, that my iterator is not a real random-access-iterator and I don't see the difference to /(*(it + n)).member/, which works. -- Sebastian Pfützner s.pfuetzner@onlinehome.de ICQ-ID: 39965036

2014/1/10 Sebastian Pfützner <s.pfuetzner@onlinehome.de>
On 09.01.2014 17:43, Krzysztof Czainski wrote:
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; }; }}
That works in the example. In my real code, /It/ is a template and I don't know how to specialize operator_brackets_result for each instantiation.
It should be possible to write a partial specialization of operator_brackets_result<> for the whole template It. For example: template < class T > class It; namespace boost { namespace detail { template < class T > struct operator_brackets_result<It<T>,T,T&> { typedef T& type; }; }} Regards Kris
participants (2)
-
Krzysztof Czainski
-
Sebastian Pfützner