Hi :)
Could you please explain to me how the end() function from vectors is working ?
I was expecting to get a l-value error when I wrote this :
1 2 3 4
vector<int>a{1,2,3};
cout<<*--a.end();
However, it worked and printed '3' successfully.
So I tried this:
1 2 3 4
int getint(){return 123;}
cout<<--getint();
But of course, I got the l-value error "expression must be a modifiable lvalue ". Where is the problem ? I thought you can 'modify' something returned by a function just if return type is reference to something.
An rvalue of class type can be used to modify the object via a call to a member function.
In your implementation, std::vector<int>::iterator is of a class type (a SCARY iterator would be of some class type).
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include <iostream>
struct A
{
int i = 5 ;
A& mem_fun( int a ) { i += a ; return *this ; }
};
A foo() { return {}; }
int main()
{
std::cout << foo().mem_fun(23).i << '\n' ;
}
For the built-in predecrement operator, the argument must be a modifiable (non-const) lvalue expression.
For user-defined operators, such as your std::vector<int>::iterator's operator--(), there are no such restrictions (and until C++11, there wasn't a consistent way to enforce them anyway), so it can be invoked with rvalue argument such as "a.end()".
For less disturbing code, you could use *(a.end()-1) or *(a.rbegin()), or *(std::prev(a.end())).
PS: the standard requirements on iterators only require predecrement for iterators of type X to work on "a value of X&", so I think a library that prohibits --a.end() by rvalue ref-qualifying its operator--'s would be conforming.. just breaking a lot of existing user code.