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