unarios sobrecargados sobrecarga relacionales operadores operador matrices insercion extraccion constructores c++ function operator-overloading

c++ - sobrecargados - sobrecarga de operadores unarios



Cuándo sobrecargar el operador de coma? (10)

Aquí hay un ejemplo de la documentación de OpenCV ( http://docs.opencv.org/modules/core/doc/basic_structures.html#mat ). El operador de coma se usa para la inicialización de cv :: Mat:

// create a 3x3 double-precision identity matrix Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);

Veo preguntas sobre SO de vez en cuando sobre la sobrecarga del operador de coma en C ++ (principalmente sin relación con la sobrecarga en sí, pero cosas como la noción de puntos de secuencia), y me hace pensar:

¿Cuándo debes sobrecargar la coma? ¿Cuáles son algunos ejemplos de sus usos prácticos?

No puedo pensar en ningún ejemplo en la parte superior de mi cabeza donde he visto o necesitado algo como

foo, bar;

en el código del mundo real, por lo que tengo curiosidad sobre cuándo (si alguna vez) se usa realmente.


Cambiemos un poco el énfasis a:

¿Cuándo debes sobrecargar la coma?

La respuesta: nunca.

La excepción: si está haciendo metaprogramación de plantillas, el operator, tiene un lugar especial en la parte inferior de la lista de prioridades del operador, que puede ser útil para construir protecciones SFINAE, etc.

Los únicos dos usos prácticos que he visto del operator, de sobrecarga son ambos en Boost :

  • Boost.Assign
  • Boost.Phoenix : es fundamental aquí ya que permite que Phoenix lambdas sea compatible con múltiples declaraciones

De forma similar al @GMan''s Boost.Assign , Blitz++ sobrecarga el operador de coma para proporcionar una sintaxis conveniente para trabajar con matrices multidimensionales. Por ejemplo:

Array<double,2> y(4,4); // A 4x4 array of double y = 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1;


En SOCI - La biblioteca de acceso a la base de datos de C ++ se utiliza para la implementación de la parte entrante de la interfaz:

sql << "select name, salary from persons where id = " << id, into(name), into(salary);

De la base de preguntas frecuentes :

P: El operador de coma sobrecargado es solo ofuscación, no me gusta.

Bien, considere lo siguiente:

"Envíe la consulta X al servidor Y y coloque el resultado en la variable Z."

Arriba, el "y" desempeña un papel de la coma. Incluso si la sobrecarga del operador de coma no es una práctica muy popular en C ++, algunas bibliotecas lo hacen, logrando una sintaxis breve y fácil de aprender. Estamos bastante seguros de que en SOCI el operador de coma se sobrecargó con un buen efecto.


En la misma línea, me enviaron una solicitud de extracción github con sobrecarga de operador de coma. Parecía algo así como seguir

class Mylogger { public: template <typename T> Mylogger & operator,(const T & val) { std::cout << val; return * this; } }; #define Log(level,args...) / do { Mylogger logv; logv,level, ":", ##args; } while (0)

entonces en mi código puedo hacer:

Log(2, "INFO: setting variable /", 1, "/"/n");

¿Alguien puede explicar por qué este es un caso de uso bueno o malo?


He usado el operador de coma para indexar mapas con múltiples índices.

enum Place {new_york, washington, ...}; pair<Place, Place> operator , (Place p1, Place p2) { return make_pair(p1, p2); } map< pair<Place, Place>, double> distance; distance[new_york, washington] = 100;


La coma tiene una propiedad interesante ya que puede tomar un parámetro de tipo void . Si es el caso, entonces se usa el operador de coma incorporado.

Esto es útil cuando quieres determinar si una expresión tiene un tipo vacío:

namespace detail_ { template <typename T> struct tag { static T get(); }; template <typename T, typename U> tag<char(&)[2]> operator,(T, tag<U>); template <typename T, typename U> tag<U> operator,(tag<T>, tag<U>); } #define HAS_VOID_TYPE(expr) / (sizeof((::detail_::tag<int>(), / (expr), / ::detail_::tag<char>).get()) == 1)

Dejo que el lector descubra como ejercicio lo que está sucediendo. Recuerde que el operator, asocia a la derecha.


Una posibilidad es la biblioteca Boost Assign (aunque estoy bastante seguro de que algunas personas considerarían este abuso en lugar de un buen uso).

Boost Spirit probablemente también sobrecarga al operador de coma (sobrecarga casi todo lo demás ...)


Uno de los usos prácticos es para utilizarlo con argumentos variables en macro. Por cierto, los argumentos variables anteriormente eran una extensión en GCC y ahora una parte del estándar C ++ 11.

Supongamos que tenemos una class X , que agrega un objeto de tipo A en ella. es decir

class X { public: X& operator+= (const A&); };

¿Qué ocurre si queremos agregar 1 o más objetos de A en el X buffer; ?
Por ejemplo,

#define ADD(buffer, ...) buffer += __VA_ARGS__

Por encima de la macro, si se usa como:

ADD(buffer, objA1, objA2, objA3);

entonces se expandirá a:

buffer += objA1, objeA2, objA3;

Por lo tanto, este será un ejemplo perfecto de usar el operador de coma, ya que los argumentos de la variable se expanden con el mismo.

Entonces, para resolver esto sobrecargamos el operador de comma y lo envolvemos += como se muestra a continuación

X& X::operator, (const A& a) { // declared inside `class X` *this += a; // calls `operator+=` }


Boost.Assign usa para que pueda hacer cosas como:

vector<int> v; v += 1,2,3,4,5,6,7,8,9;

Y lo he visto usado para hacks de lenguaje extravagantes, voy a ver si puedo encontrar alguno.

Ajá, recuerdo uno de esos usos estrafalarios: coleccionar expresiones múltiples . (Advertencia, magia oscura.)