programacion plantillas funciones ats c++ c++11 move-semantics perfect-forwarding universal-reference

funciones - plantillas c++



¿Deberían escribirse todas las funciones/más setter en C++ 11 como plantillas de funciones que acepten referencias universales? (1)

Considere una clase X con N variables miembro, cada uno de algunos tipos copiable y móvil , y N funciones setter correspondientes. En C ++ 98, la definición de X probablemente se vería así:

class X { public: void set_a(A const& a) { _a = a; } void set_b(B const& b) { _b = b; } ... private: A _a; B _b; ... };

Las funciones Setter de la clase X anterior pueden vincularse tanto a lvalue como a rvalue arguments. Dependiendo del argumento real, esto podría resultar en la creación de un temporal y eventualmente resultará en una asignación de copia; debido a esto, los tipos no copiables no son compatibles con este diseño.

Con C ++ 11 tenemos semántica de movimiento, reenvío perfecto y referencias universales (terminología de Scott Meyers), que permiten un uso más eficiente y generalizado de las funciones del colocador al reescribirlas de esta manera:

class X { public: template<typename T> void set_a(T&& a) { _a = std::forward<T>(a); } template<typename T> void set_b(T&& b) { _b = std::forward<T>(b); } ... private: A _a; B _b; ... };

Las referencias universales pueden vincularse a const / const - const , volatile / no volatile , y a cualquier tipo convertible en general, evitando la creación de valores temporales y pasando valores directamente a operator = . Los tipos movibles no copiables ahora son compatibles. Posiblemente los enlaces no deseados se pueden eliminar a través de static_assert o mediante std::enable_if .

Así que mi pregunta es: como una guía de diseño , ¿deberían escribirse todas las funciones de setter (por ejemplo, la mayoría) en C ++ 11 como plantillas de funciones que aceptan referencias universales?

Además de la sintaxis más engorrosa y la imposibilidad de utilizar herramientas de ayuda tipo Intellisense al escribir código en esas funciones de setter, ¿hay desventajas relevantes con el principio hipotético de " funciones de establecimiento de escritura como plantillas de función que aceptan referencias universales siempre que sea posible "?


Usted conoce las clases A y B, para saber si son móviles o no y si este diseño es finalmente necesario. Para algo como std::string , es una pérdida de tiempo cambiar el código existente a menos que sepa que aquí tiene un problema de rendimiento. Si está tratando con auto_ptr , entonces es hora de arrancarlo y usar unique_ptr .

Por lo general, se prefiere ahora tomar argumentos por valor si no conoce algo más específico, como

void set_a(A a) { _a = std::move(a); }

Esto permite el uso de cualquiera de los constructores de A sin requerir nada más que la movilidad y ofrece una interfaz relativamente intuitiva.