Título: Uso de Threads y error de compilación asignado a una libreria estandar... Publicado por: digimikeh en 4 Agosto 2019, 00:58 am Buenas..
Tengo este código y me está saliendo error, ppienso que la sintaxis está correcta.. aun no entiendo por qué el error.. Alguna pista? Ver en el siguiente enlace el codigo para probar: https://onlinegdb.com/ryO2ptQ7B (https://onlinegdb.com/ryO2ptQ7B) Saludos. Edit : Le quite el simbolo de referencia en el parámetro para la funcion de la linea 5 y ahí compiló.. Pero no veo por qué... Título: Re: Uso de Threads y error de compilación asignado a una libreria estandar... Publicado por: Loretz en 4 Agosto 2019, 21:17 pm ...
Citar Le quite el simbolo de referencia en el parámetro para la funcion de la linea 5 y ahí compiló.. Pero no veo por qué... Para poner las cosas más a mano, quitando de tu ejemplo lo que no viene al caso: Código
Y dices que si quitas la referencia, si la función "f" toma su argumento por valor, entonces compila sin error. Está bien, y quisieras saber por qué... Porque el constructor de thread que estás invocando es: Código: template< class Function, class... Args > Ver: https://en.cppreference.com/w/cpp/thread/thread/thread (https://en.cppreference.com/w/cpp/thread/thread/thread)explicit thread( Function&& f, Args&&... args ); Y en ese caso, en las NOTAS, se aclara que Citar "The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with std::ref or std::cref). " NO es que lo esté aclarando, sólo se dice que "Así debe ser", Entonces, en tu ejemplo, podrías poner: Código
Funciona así porque std::ref devuelve ese wrapper que necesitas en el segundo argumento template, que se pasa por valor, pero se comporta como una referencia (encapsula, contiene, envuelve una referencia). https://en.cppreference.com/w/cpp/utility/functional/ref (https://en.cppreference.com/w/cpp/utility/functional/ref) Pero preguntabas "por qué". Bueno, porque al construir la instancia de thread, en su constructor se invoca a la función del primer parámentro, con los parámetros del segundo parámetro, ¿de acuerdo?, pero esa llamada a f se hace a través de Código
Donde se invoca la función f con el "parameter pack" que devuelva "decay_copy", ¿verdad? Pero esa "decay_copy" sólo hace un "forward" del pack que recibe, y devuelve a su vez un std::decay_t. Y, ajá, acá está, es eso. Si te fijas en la documentación sobre std::dacay_t: https://en.cppreference.com/w/cpp/types/decay (https://en.cppreference.com/w/cpp/types/decay) verás que para este caso: Citar the member typedef type is std::remove_cv<std::remove_reference<T>::type>::type. These conversions model the type conversion applied to all function arguments when passed by value. Ahorá sí, no sólo está aplicando std::remove_cv, que no tiene que ver con lo nuestro en este momento, sino que, fundamentalmente, aplica std::remove_reference al T::type que recibe como parámetro, que eso sí termina de explicar por qué necesitamos un wrapper cuando la función que se va a ejecutar en el nuevo thread toma sus parámetros por referencia. Quise editar mi respuesta anterior y quedó una completa basura, así que escribo aquí a modo de apéndice: Otra variante para considerar es que el parámetro de f sea una const reference: Código: void f(const std::vector<double>& vd) o, como hay quien prefiere: Código: void f(std::vector<double> const& vd) (con el "const" antes de &) |