Discussion:
[iterator] error while accessing member of result of brackets-operator
Sebastian Pfützner
2014-01-09 15:37:06 UTC
Permalink
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
***@onlinehome.de
ICQ-ID: 39965036
Krzysztof Czainski
2014-01-09 16:43:46 UTC
Permalink
Post by Sebastian Pfützner
Hello,
the following code does not compile with the last line in main(). The
error message is
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;
};
public boost::iterator_facade<It, S, boost::random_access_
traversal_tag>
{
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
Sebastian Pfützner
2014-01-10 09:54:26 UTC
Permalink
Post by Krzysztof Czainski
That said, here's a hack for you: right after the definition of struct S
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
***@onlinehome.de
ICQ-ID: 39965036
Krzysztof Czainski
2014-01-10 10:10:07 UTC
Permalink
Post by Krzysztof Czainski
That said, here's a hack for you: right after the definition of struct S
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

Continue reading on narkive:
Loading...