c++ c++11 portability correctness

c++ - ¿Cuándo es necesario el uso de std:: ref?



c++11 portability (3)

Considerar:

std::tuple<int , const A&> func (const A& a) { return std::make_tuple( 0 , std::ref(a) ); }

¿Es necesario el std::ref para escribir código correcto y portátil? (Se compila bien sin ella)

Fondo:

Si elimino std::ref mi código se compila bien sin ninguna advertencia ( g++-4.6 -Wall ), pero no se ejecuta correctamente.

En caso de interés la definición de A :

struct A { std::array<int,2> vec; typedef int type_t; template<typename... OPs,typename... VALs> A& operator=(const std::pair< std::tuple<VALs...> , std::tuple<OPs...> >& e) { for( int i = 0 ; i < vec.size() ; ++i ) { vec[i] = eval( extract(i,e.first) , e.second ); } } };


Uno de los ejemplos donde std::ref es necesario:

void update(int &data) //expects a reference to int { data = 15; } int main() { int data = 10; // This doesn''t compile as the data value is copied when its reference is expected. //std::thread t1(update, data); std::thread t1(update, std::ref(data)); // works t1.join(); return 0; }

El constructor std::thread copia los valores proporcionados, sin convertirlos al tipo de argumento esperado (que es el tipo de referencia en este caso, vea update() ). Así que necesitamos envolver los argumentos que realmente necesitan ser referencias en std::ref .


std::ref no hace una referencia, por lo que en su ejemplo de código no hace lo que espera. std::ref crea un objeto que se comporta de manera similar a una referencia. Puede ser útil, por ejemplo, cuando desee crear una instancia de un functor y pasar una versión de referencia a un algoritmo de biblioteca estándar. Como los algoritmos toman funtores por valor, puede usar std::ref para envolver el funtor.


  • make_tuple(0, a) hace una tuple<int, A> .
  • make_tuple(0, ref(a)) hace una tuple<int, reference_wrapper<A>> .
  • También puede decir tuple<int, A&> t(0, a); para una tupla que no puedes hacer con make_tuple , o usa std::tie .