¿Este uso del operador", " se considera de mala forma?


He creado una clase list como un medio para reemplazar funciones variádicas en mi programa usadas para inicializar objetos que necesitan contener una lista cambiante de elementos. La clase list tiene una sintaxis de uso que realmente me gusta. Sin embargo, no lo he visto usado antes, así que me preguntaba si no debería usarlo solo por ese hecho. Una implementación básica de la clase list se ve así...

#include <list>
#include <iostream>
template<typename T>
struct list
{
    std::list<T> items;
    list(const list&ref):items(ref.items){}
    list(){}
    list(T var){items.push_back(var);}
    list& operator,(list add_){
        items.insert(items.end(),add_.items.begin(), add_.items.end());
        return *this;
    }
    list& operator=(list add_){
        items.clear();
        items.insert(items.end(),add_.items.begin(), add_.items.end());
        return *this;
    }
    list& operator+=(list add_){
        items.insert(items.end(),add_.items.begin(), add_.items.end());
        return *this;
    }
};

Esto me permite usar esto en código de esta manera...

struct music{
//...
};
struct music_playlist{
    list<music> queue;
//...
};
int main (int argc, const char * argv[])
{
    music_playlist playlist;
    music song1;
    music song2;
    music song3;
    music song4;
    playlist.queue = song1,song2; // The queue now contains song1 and song2
    playlist.queue+= song1,song3,song4; //The queue now contains two song1s and song2-4
    playlist.queue = song2; //the queue now only contains song2
    return 0;
}

, realmente creo que la sintaxis es mucho más agradable de lo que sería si hubiera expuesto un contenedor stl normal, e incluso más agradable (y typesafe) que las funciones variádicas. Sin embargo, dado que no he visto esta sintaxis utilizada, tengo curiosidad sobre si debo evitarlo, porque sobre todo el código debe ser fácilmente entendido por otros programadores?

EDITAR:

En conjunto con esta pregunta, he publicado esta pregunta más dirigida a las soluciones al problema real.

Author: Community, 2011-07-18

8 answers

¿Por qué no sobrecargar el operador << como lo hace QList? Entonces úsalo como:

playlist.queue << song1 << song2; // The queue now contains song1 and song2
playlist.queue << song1 << song3 << song4; //The queue now contains two song1s and song2-4
 40
Author: rgngl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-18 05:19:25

Estoy de acuerdo en que su sintaxis se ve bien como la ha escrito.
Mi principal dificultad con el código es que esperaría que lo siguiente sea el mismo

playlist.queue = song1,song2;
playlist.queue = (song1,song2);  //more of c-style, as @Iuser notes.

Mientras que en realidad son completamente diferentes.

Esto es peligroso porque es demasiado fácil introducir errores de uso en el código. Si a alguien le gusta usar paréntesis para agregar énfasis adicional a las agrupaciones (no es raro), entonces la coma podría convertirse en un verdadero dolor. Para ejemplo,

//lets combine differnt playlists
new_playlist.queue =    song1        //the first playlist
                      ,(song3,song4) //the second playlist //opps, I didn't add song 3!
                      , song5;        //the third 

O

new_playlist.queue = (old_playlist.queue, song6); //opps, I edited my old playlist too!

Incidentemente, te has encontrado con boost.asignar: http://www.boost.org/doc/libs/1_47_0/libs/assign/doc/index.html

 20
Author: Tom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-18 06:48:41

¿Ha cambiado la precedencia recientemente?

playlist.queue = song1,song2;

Esto debería analizarse como:

(playlist.queue = song1) , song2;

Su ', ' y '+ = ' son los mismos! Sería una mejor coincidencia semántica si su operador de coma creara una lista temporal, insertara los elementos izquierdo y derecho y devolviera los temporales. Entonces podrías escribirlo así;

playlist.queue = (song1,song2);

Con paréntesis explícitos. Eso le daría a los programadores C una oportunidad de luchar para poder leer el código.

 11
Author: luser droog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-18 05:37:13

Un pequeño problema es que si el compilador no puede elegir su coma de operador sobrecargada, puede recurrir al uso del operador incorporado.

En contraste, con Boost.Asignar mezclar tipos produce un error de compilación.

#include <boost/assign.hpp>

int main()
{
    int one = 1;
    const char* two = "2";
    list<int> li;
    li = one, two;

    using namespace boost::assign;
    std::list<int> li2;
    li2 += one, two;
}
 7
Author: UncleBens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-18 06:50:57

Esto es probablemente algo que pertenece a los programadores, pero aquí están mis dos centavos.

Si estás hablando de código que tiene un contexto bastante estrecho, donde los usuarios lo usarán en un par de lugares y eso es todo, entonces sobrecargar el operador , probablemente esté bien. Si estás creando un lenguaje específico de dominio que se usa en un dominio en particular y en ningún otro lugar, probablemente esté bien.

El problema viene cuando lo estás sobrecargando por algo que esperas que el usuario utilizar con cierta frecuencia.

Sobrecargar , significa que el lector necesita reinterpretar completamente cómo lee su código. No pueden simplemente mirar una expresión y saber instantáneamente lo que hace. Estás jugando con algunas de las suposiciones más básicas que los programadores de C++ hacen cuando se trata de escanear código.

Haz eso bajo tu propio riesgo.

 5
Author: Nicol Bolas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-18 05:27:14

Tengo curiosidad sobre si debo evitarlo, porque sobre todo el el código debe ser fácilmente comprendido por otros programadores

Si el objetivo es hacer que su código sea fácil de entender para otros programadores de C++, anular operadores para darles un significado que es muy diferente del del C++ estándar no es un buen comienzo. Los lectores no deberían tener que a) entender cómo ha implementado su contenedor y b) recalibrar su comprensión de los operadores estándar solo para ser capaz de dar sentido a su código.

Puedo apreciar el precedente de impulso para este tipo de cosas. Si está bastante seguro de que la mayoría de las personas que leerán su código también estarán familiarizadas con Boost Assign, su propia anulación del operador, podría ser bastante razonable. Aún así, sugeriría seguir la sugerencia de @badzeppelin de usar operator

cout << "Hello world!"`

Y su anexo la operación es muy similar a escribir en una secuencia.

 5
Author: Caleb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-18 07:53:30

Es malo en muchos niveles...

Estás anulando list y siguiendostd::list. Un gran no-no. Si desea que su propia clase de lista - que sea con un nombre diferente, no sombra de la biblioteca estándar.

Usar , de esta manera no es legible. El valor devuelto del operador es el operando correcto. Incluso si su código funciona, para un lector externo no será obvio por qué, y es algo malo. El código debe ser legible, no agradable.

 4
Author: littleadv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-18 05:13:12

No hay nada malo en usar coma operator , usando específicamente. Cualquier operador deja mal gusto, si se explota. En tu código, no veo ningún problema razonable. Solo una sugerencia, me gustaría dar es:

list& operator,(list &add_){  // <--- pass by reference to avoid copies
  *this += add_;  // <--- reuse operator +=
  return *this;
}

De esta manera, siempre tienes que editar solo operator +=, si quieres algún cambio en la lógica. Tenga en cuenta que, mi respuesta está en la perspectiva de la legibilidad y el mantenimiento del código en general. No voy a plantear la preocupación sobre la lógica de negocios que utiliza.

 2
Author: iammilind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-18 05:13:45