Considerando:

template <typename... Args>
ResourceHolder& operator+=(const ResourceInserter<Key, Args...>& inserter) {

    if constexpr (sizeof...(Args) == 0) {
        insert(std::move(inserter.key),
               std::move(inserter.fileName));
    } else {
        insert(std::move(inserter.key),
               std::move(inserter.fileName),
               std::move(std::get<Args...>(inserter.tuple)));
    }

    return *this;
}

¿Crees que este es un uso correcto de la semántica de movimiento?

La instancia inserter de ResourceInserter se pasa como una referencia constante.

1
weno 27 may. 2020 a las 19:13

3 respuestas

La mejor respuesta

Mover objetos constantes generalmente es una copia simple (a menos que sobrecargue Object(const Object&&)), por lo que su uso de std::move parece inútil.

Si los miembros de ResourceInserter son referencias (no constantes), tu const ResourceInserter& es "engañoso", y tu movimiento realmente sucederá.

2
Jarod42 27 may. 2020 a las 16:30

Contrariamente a su nombre, std :: move en realidad no mueve nada. Simplemente le dice al compilador que intente moverse (es decir, indicar que un objeto t se puede "mover de" al convertirlo al tipo de referencia rvalue [más específicamente, produciendo expresión xvalue]).

Sin embargo, su clase no tiene un constructor que acepte un const inserter&&, en su lugar utilizará el copie el constructor de su clase (ya sea implícita o explícita), y copie de forma segura. Sin peligro, sin trampa. Si el constructor de copias está deshabilitado por algún motivo, recibirá un error de compilación.

Prueba esto:

#include <iostream>
struct Test {
   Test() { }
   Test(const Test& ) { std::cout << "COPY" << std::endl; }
   Test(Test&&)       { std::cout << "MOVE" << std::endl; }
};

int main() 
{
    const Test t;
    Test t2 = std::move(t);
    return 0;
}

Imprime COPY, no MOVE.

2
abhiarora 27 may. 2020 a las 16:32

No.

Está enviando a const Key && etc. Key::Key(const Key&&) generalmente no puede hacer nada útil, por lo que estará copiando.

Usted podría querer tener un par de sobrecargas

template <typename... Args>
ResourceHolder& operator+=(const ResourceInserter<Key, Args...>& inserter) {

    if constexpr (sizeof...(Args) == 0) {
        insert(inserter.key,
               inserter.fileName);
    } else {
        insert(inserter.key,
               inserter.fileName,
               std::get<Args...>(inserter.tuple));
    }

    return *this;
}

template <typename... Args>
ResourceHolder& operator+=(ResourceInserter<Key, Args...>&& inserter) {

    if constexpr (sizeof...(Args) == 0) {
        insert(std::move(inserter.key),
               std::move(inserter.fileName));
    } else {
        insert(std::move(inserter.key),
               std::move(inserter.fileName),
               std::move(std::get<Args...>(inserter.tuple)));
    }

    return *this;
}

Dónde te mueves de los miembros de un valor r inserter

2
Caleth 27 may. 2020 a las 16:20