2

This code won't compile:

for(vector<Box>::iterator it = shapes.end(); it >= shapes.begin(); --it){
    *it.update(1,1);
    *it.draw();
}

It claims:

main.cpp:80:17: error: ‘std::vector<Box>::iterator’ has no member named ‘update’
main.cpp:81:17: error: ‘std::vector<Box>::iterator’ has no member named ‘draw’

However AFAIK, that code doesn't try and call vector::iterator.draw(), it dereferences the iterator, which should give me an object of my class box, which does have those methods. What am I doing wrong, and sorry for the awful title.

linguanerd
  • 751
  • 3
  • 11
w4etwetewtwet
  • 1,330
  • 2
  • 10
  • 20
  • 1
    Beware of precedence. `*it.update(1,1);` is not the same as `(*it).update(1,1);`, which could written as `it->update(1,1);` for the sake of readability. –  Jul 14 '13 at 20:18

2 Answers2

8

It's a matter of operator precedence.

Operator . has higher precedence than operator *. Use parenthesis to force operator * application first.

(*it).update(1,1);
(*it).draw();

You can also use operator -> on iterators.

it->update(1,1);
it->draw();

Also see: What is the difference between the dot (.) operator and -> in C++? and cppreference: Member access operators.


@andre stated correctly that you can also use reverse iterators to iterate over a sequence in reverse order but you should use them correctly.
for(vector<Box>::reverse_iterator it = shapes.rbegin(); it != shapes.rend(); ++it)
{
  it->update(1,1);
  it->draw();
}
Community
  • 1
  • 1
Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
  • Thanks, that worked perfectly, I take it that it was trying to call the update method of iterator, and then dereference the output of that. I will accept ASAP. – w4etwetewtwet Jul 14 '13 at 20:19
  • You're right. (Such issues are much harder to find if the reversed order of the operators compiles. (If any overloaded `operator *` of type A returns an object of type B which has a member function with the same signature as A...) – Pixelchemist Jul 14 '13 at 20:25
1

also, to add on @Pixelchemist 's answer.

for(vector<Box>::iterator it = shapes.end(); it >= shapes.begin(); --it){
    *it.update(1,1);
    *it.draw();
}

should be:

for(vector<Box>::reverse_iterator it = shapes.rbegin(); it != shapes.rend(); ++it){
    *it.update(1,1);
    *it.draw();
}

rend and rbeing are used to iterate in reverse.

andre
  • 7,018
  • 4
  • 43
  • 75
  • If you replace the type of `it` by `reverse_iterator` and iterate until `it!=shapes.rend()` then your example is correct (finally^^) ;) – Pixelchemist Jul 14 '13 at 20:34
  • Thanks, that actually fixed another problem I was having. – w4etwetewtwet Jul 14 '13 at 20:36
  • You're loop condition is still using `operator >=`. Since an end iterator is one-past the end of the data per definition, the `=` would result in undefnied behaviour, even if `>` would be correct, (which is not the case). If you do not want to use `!=` then replace `>=` by `<` (which is in fact the exact opposite `!(>=)` since reverse_iterator is the opposite of the iterator so you'll have to reverse the condition as well.) – Pixelchemist Jul 14 '13 at 20:43