4

Consider this code:

struct CData
{
    int bar() { return 1; }
};

int main()
{
    typedef boost::numeric::ublas::vector<CData> vec_data_t;

    vec_data_t foo;
    for (vec_data_t::iterator it = foo.begin();
         it != foo.end();
         ++it)
    {
        std::cout << it->bar() << std::endl;    // COMPILE ERROR!
        std::cout << (*it).bar() << std::endl;  // ok
    }

    return 0;
}

Why does the first line in the loop using the arrow operator fail to compile, while the next line using operator* works fine? I'm used to using the arrow operator with std container iterators and wonder why it fails with boost::numeric::ublas iterators.

I'm using boost 1.54 and gcc 4.9.1 and the exact error message is:

 error: base operand of ‘->’ has non-pointer type ‘boost::numeric::ublas::vector<CData>::iterator’
oxygene
  • 621
  • 4
  • 14

2 Answers2

3

I'd say it's a bug in Boost. According to the documentation, boost::numeric::ublas::vector models a Vector Expression, which provides an Indexed Bidirectional iterator, which (among other things) lists the following as a valid expression and its semantics:

Member access | it->m | Type requirements T is a type for which t.m is defined.


Member access | it->m | Precondition it is dereferenceable. | Semantics Equivalent to (*it).m

Looking into the code shows that the indexed_iterator class template does not define operator->. According to the docs, it clearly should.

You might want to look for a bug report and if there is none, file one.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
0

Because operator->() is an extremely difficult operator to implement right.

Any non-trivial custom iterator that I ever saw doesn't implement ->. My guess is that the uBlas implementors didn't know how to do it (and I don't blame them).

The problem of course is to guarantee that there is a pointer at the end of the -> chain, and on top of that for it->bla to have the same meaning as (*it).bla

alfC
  • 14,261
  • 4
  • 67
  • 118