Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the compiler allow vector.begin()=vector.end() in C++?

Tags:

c++

std

vector

While learning about iterators in C++ I tried the following:

#include <vector>

int main() {
    std::vector<int> a;
    a.end()=a.begin();
    //Why is this even allowed by the compiler?
}

What am I missing?

like image 441
4nt Avatar asked Sep 21 '14 11:09

4nt


3 Answers

it would not be posiible if for example function end would return a pointer.

For example this code will not be compiled

int a[] = { 1, 2, 3 };

std::end( a ) = std::begin( a );

GCC issues error

error: lvalue required as left operand of assignment
  std::end( a ) = std::begin( a );
                ^

However when objects of class types are used then they can call the ovetloaded copy (or move) assignment operator.

So the question arises why do not the functions return constant iterator objects. I think that it would be possible to apply operator ++. For example

auto it = ++c.begin();

For direct access iterators as pointers you can write simply

auto it = begin( a ) + 1;
like image 52
Vlad from Moscow Avatar answered Sep 21 '22 21:09

Vlad from Moscow


The standard doesn't specify whether std::vector::iterator is a class type, or a raw pointer.

If it is a class type then this code calls operator= on the temporary object returned by a.end(). Not a very useful operation, but legal. (Rvalues may have functions called on them).

If your library makes std::vector::iterator be a pointer then this code would fail to compile, since simple assignment requires an lvalue on the left.

Jarod42 pointed out that if the iterator's assignment operator had been defined as:

std::vector::iterator& std::vector::iterator::operator =(std::vector::iterator) &;

then this code would be illegal; the trailing & means that the function is only selectable when it is being called on an lvalue.

But it wasn't defined that way, I would guess that the Committee didn't want to make some legal code illegal for no good reason; maybe there is a use case for it that nobody thought of yet.

like image 27
M.M Avatar answered Sep 23 '22 21:09

M.M


The line affect a temporary iterator, and so is useless.

std::vector::iterator = std::vector::iterator is allowed.

A way to disallow that would be to have

std::vector::iterator::operator =(std::vector::iterator) &; // note the extra &

but std::vector::iterator may be a simple pointer, and we can't disalow T* = T*

like image 30
Jarod42 Avatar answered Sep 22 '22 21:09

Jarod42