end() returns lvalue ?

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' ;
}

http://coliru.stacked-crooked.com/a/f4a516ff6870d650
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.
Last edited on
Thanks,you saved me again.It makes sense now :).
Topic archived. No new replies allowed.