It depends on how the iterator is defined.
It seems that for the class template std::array the iterator is defined as a pointer. So the functions begin, end. cbegin, cend return just the pointer. Thus as the pointer is returned by value you may not decrease it because an lvalue is required..
For the class template std::vector the iterator is defined as a user-defined class for which the operator --() is defined.
Consider the following demonstrative program
#include <iostream>
class Int
{
public:
Int( int x = 0 ) : x ( x )
{
}
Int & operator --()
{
--x;
return *this;
}
friend std::ostream & operator <<( std::ostream &os, const Int &i )
{
return os << i.x;
}
private:
int x;
};
int f( int x )
{
return x;
}
Int f( Int x )
{
return x;
}
int main()
{
std::cout << --f( Int( 10 ) ) << std::endl;
// error: lvalue required as decrement operand
// std::cout << --f( 10 ) << std::endl;
return 0;
}
Take into account that you can write
auto arrIt = std::prev( arr.end() );
instead of
auto arrIt = --arr.end();
provided that you include header <iterator>.
You can use the operator with the reverse iterators of the class template std::array because the Standard defines them explicitly like
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
and the user-defined class std::reverse_iterator defines the operator --() .
Here is a demonstrative program
#include <iostream>
#include <array>
int main()
{
std::array<double, 2> arr = { { 1, 2 } };
auto it = --arr.rend();
std::cout << *it << std::endl;
return 0;
}