c++ c++11 for-loop universal-reference forwarding-reference

c++ - ¿Qué hace `auto && e` en los bucles de bucles basados en rango?



c++11 for-loop (1)

Suponiendo que mi regla actual al programar con bucles basados ​​en rangos dice

Use for(auto const &e :...) o for(auto &e:...) cuando sea posible una vez más for(auto a: ...) .

Baso esto en mi propia experiencia y en esta pregunta, por ejemplo.

Pero después de leer sobre el nuevo resumen de bucles, me pregunto: ¿no debería reemplazar mi & en mi regla con && ? Como está escrito here esto se parece a las Referencias Universales de Meyers .

Entonces, me pregunto, si mi nueva regla es

Use for(auto const &&e :...) o for(auto &&e:...) cuando sea posible ...

¿O eso no siempre funciona y, por lo tanto, debería ser bastante complicado?

Marque si es posible for(auto const &&e :...) o for(auto &&e:...) , luego considere for(auto const &e :...) o for(auto &e:...) , y solo Cuando sea necesario no utilice referencias.


Howard Hinnant ha explicado muy bien cuándo y si debe usar auto&& in para bucles.

Esto deja la pregunta de qué x en

auto &&x = ...expr...

en realidad es. Y se maneja como si hubiera una definición de plantilla de función.

template <class U> void f(const U& u);

y el tipo de x se deduce por los mismos tules que u [§7.1.6.4. (7)].

Esto significa que no se maneja como una referencia RValue, sino como una "Referencia universal / de reenvío"; se aplican las " Reglas de colapso de referencia".

Esto también vale para

const auto &&x = ...expr...

como se muestra en el ejemplo de §7.1.6.4. (7), al menos para const auto &x .

Pero, como dice PiotrS en los comentarios de las preguntas, cualquiera de los calificadores anula la urgencia:

no, porque ni T en la template<class T> void f(const T&&) es una referencia de reenvío, ni const auto&& es. El hecho de que T&& en la declaración de parámetros no implica que esté remitiendo la referencia. Solo T&& puro sin calificadores como const o volatile es referencia de reenvío, lo que significa que tiene que ser template<class T> void f(T&&) o auto&& , y nunca const T&& o const auto&&