inicializador_lista y semántica de movimiento

Resuelto fredoverflow asked hace 12 años • 8 respuestas

¿ Puedo mover elementos fuera de a std::initializer_list<T>?

#include <initializer_list>
#include <utility>

template<typename T>
void foo(std::initializer_list<T> list)
{
    for (auto it = list.begin(); it != list.end(); ++it)
    {
        bar(std::move(*it));   // kosher?
    }
}

Dado que std::intializer_list<T>requiere una atención especial del compilador y no tiene una semántica de valor como los contenedores normales de la biblioteca estándar de C++, prefiero prevenir que lamentar y preguntar.

fredoverflow avatar Nov 19 '11 16:11 fredoverflow
Aceptado

No, eso no funcionará según lo previsto; Aún recibirás copias. Estoy bastante sorprendido por esto, ya que pensé que initializer_listexistía para mantener una variedad de temporales hasta que fueran moveterminados.

beginy endpara initializer_listreturn const T *, por lo que el resultado de movesu código es T const &&: una referencia de valor r inmutable. No se puede cambiar significativamente de una expresión así. Se vinculará a un parámetro de función de tipo T const &porque los valores r se vinculan a referencias de valores l constantes y aún verá la semántica de copia.

Probablemente la razón de esto es que el compilador puede optar por hacer que sea initializer_listuna constante inicializada estáticamente, pero parece que sería más limpio hacer su tipo initializer_listo const initializer_lista discreción del compilador, por lo que el usuario no sabe si esperar una variable consto una variable . resultado de beginy end. Pero ese es sólo mi presentimiento, probablemente hay una buena razón por la que estoy equivocado.

Actualización: escribí una propuesta ISO para initializer_listadmitir tipos de solo movimiento. Es sólo un primer borrador y aún no está implementado en ninguna parte, pero puede verlo para analizar más el problema.

Potatoswatter avatar Nov 19 '2011 09:11 Potatoswatter
bar(std::move(*it));   // kosher?

No de la forma que pretendes. No puedes mover un constobjeto. Y std::initializer_listsolo proporciona constacceso a sus elementos. Entonces el tipo de ites const T *.

Su intento de igualar std::move(*it)sólo resultará en un valor l. Es decir: una copia.

std::initializer_listhace referencia a la memoria estática . Para eso es la clase. No se puede mover de la memoria estática, porque el movimiento implica cambiarla. Sólo puedes copiar de él.

Nicol Bolas avatar Nov 19 '2011 16:11 Nicol Bolas