loop instead for based c++ c++11 iterator standards type-safety

c++ - instead - ¿Por qué "std:: begin()" siempre devuelve "const_iterator" en tal caso?



for each c++ (2)

#include <vector> #include <iostream> using namespace std; int main() { vector<int> coll; decltype(std::begin(std::declval<vector<int>>())) pos_1 = coll.begin(); auto pos_2 = coll.begin(); cout << typeid(decltype(pos_1)).name() << endl; cout << typeid(decltype(pos_2)).name() << endl; }

Mi compilador tiene un clang 4.0. El resultado es:

class std::_Vector_const_iterator<class std::_Vector_val<struct std::_Simple_types<int> > > class std::_Vector_iterator<class std::_Vector_val<struct std::_Simple_types<int> > >

Eso significa: pos_1 = pos_2; está bien, mientras que pos_2 = pos_1; No está bien.

¿Por qué std::begin() siempre devuelve const_iterator lugar de const_iterator en tal caso?


La llamada a la función:

std::declval<std::vector<int>>()

da como resultado una expresión rvalue que se puede denotar como:

std::vector<int>&&

El compilador tiene dos sobrecargas (genéricas) de std::begin para elegir de ( [iterator.range] ):

template <class C> auto begin(C& c) -> decltype(c.begin()); // #1 template <class C> auto begin(const C& c) -> decltype(c.begin()); // #2

Para una expresión rvalue, solo la segunda sobrecarga (n. ° 2) es viable: un valor r no puede estar vinculado por una referencia de valor l no const. La calificación const del tipo referenciado implica que el compilador usará la sobrecarga const calificada de la función begin member:

const_iterator begin() const noexcept; // ~~~~^

que devuelve una instancia de tipo const_iterator .

Puede cambiar ese comportamiento solicitando una expresión lvalue de std::vector<int> desde la llamada std::declval :

decltype(std::begin(std::declval<std::vector<int>&>())) pos_1 = coll.begin(); // ~~^~~


si tiene Type&& (a temporary), entonces la resolución de sobrecarga preferirá const Type& over Type& , ya que un enlace temporal no se unirá a una referencia de lvalue no const