¿Por qué nadie parece usar tuplas en C ++, ya sea Boost Tuple Library o la biblioteca estándar para TR1? He leído mucho código C ++, y muy rara vez veo el uso de tuplas, pero a menudo veo muchos lugares donde las tuplas resolverían muchos problemas (generalmente devolviendo valores múltiples de las funciones).
Las tuplas te permiten hacer todo tipo de cosas geniales como esta:
tie(a,b) = make_tuple(b,a); //swap a and b
Eso es ciertamente mejor que esto:
temp=a;
a=b;
b=temp;
Por supuesto, siempre puedes hacer esto:
swap(a,b);
Pero, ¿qué pasa si quieres rotar tres valores? Puedes hacer esto con tuplas:
tie(a,b,c) = make_tuple(b,c,a);
Las tuplas también hacen que sea mucho más fácil devolver múltiples variables de una función, lo cual es probablemente un caso mucho más común que intercambiar valores. Usar referencias a valores de retorno ciertamente no es muy elegante.
¿Hay grandes inconvenientes para las tuplas en las que no estoy pensando? Si no, ¿por qué rara vez se usan? ¿Son más lentos? ¿O es solo que la gente no está acostumbrada a ellos? ¿Es una buena idea usar tuplas?
a = a ^ b; b = a ^ b; a = a ^ b;
Respuestas:
Porque aún no es estándar. Cualquier cosa no estándar tiene un obstáculo mucho mayor. Las piezas de Boost se han vuelto populares porque los programadores clamaban por ellas. (hash_map salta a la mente). Pero aunque la tupla es útil, no es una victoria tan abrumadora y clara que la gente se moleste con ella.
fuente
Una respuesta cínica es que muchas personas programan en C ++, pero no entienden y / o usan la funcionalidad de nivel superior. A veces es porque no están permitidos, pero muchos simplemente no lo intentan (ni siquiera entienden).
Como un ejemplo sin impulso: ¿cuántas personas usan la funcionalidad que se encuentra en
<algorithm>
?En otras palabras, muchos programadores de C ++ son simplemente programadores de C que usan compiladores de C ++, y quizás
std::vector
ystd::list
. Esa es una razón por la cual el uso deboost::tuple
no es más común.fuente
La sintaxis de tupla de C ++ puede ser bastante más detallada de lo que a la mayoría de la gente le gustaría.
Considerar:
Entonces, si desea hacer un uso extensivo de las tuplas, puede obtener tuple typedefs en todas partes u obtener nombres de tipo molestamente largos en todas partes. Me gustan las tuplas Los uso cuando sea necesario. Pero generalmente se limita a un par de situaciones, como un índice de elementos N o cuando se usan mapas múltiples para vincular los pares de iteradores de rango. Y generalmente tiene un alcance muy limitado.
Todo es muy feo y hacky en comparación con algo como Haskell o Python. Cuando C ++ 0x llegue aquí y obtengamos las tuplas de palabras clave 'auto' comenzarán a parecer mucho más atractivas.
La utilidad de las tuplas es inversamente proporcional al número de pulsaciones de teclas necesarias para declararlas, empaquetarlas y desempaquetarlas.
fuente
Para mí, es un hábito, sin lugar a dudas: las tuplas no resuelven ningún problema nuevo para mí, solo algunas que ya puedo manejar bien. El intercambio de valores todavía se siente más fácil a la antigua usanza y, lo que es más importante, realmente no pienso en cómo intercambiar "mejor". Es lo suficientemente bueno como está.
Personalmente, no creo que las tuplas sean una gran solución para devolver múltiples valores, parece un trabajo para
struct
s.fuente
Pero, ¿qué pasa si quieres rotar tres valores?
Bien, entonces con 4 valores de etc., eventualmente la n-tupla se convierte en menos código que n-1 intercambios. Y con el intercambio predeterminado, esto hace 6 asignaciones en lugar de las 4 que tendría si implementara una plantilla de tres ciclos usted mismo, aunque espero que el compilador lo resuelva para tipos simples.
Puede crear escenarios en los que los intercambios sean difíciles de manejar o inapropiados, por ejemplo:
Es un poco incómodo desempacar.
Sin embargo, el punto es que hay formas conocidas de tratar las situaciones más comunes para las que las tuplas son buenas y, por lo tanto, no hay una gran urgencia para tomarlas. Por lo menos, no estoy seguro de que:
no hace 6 copias, lo que lo hace completamente inadecuado para algunos tipos (las colecciones son las más obvias). Siéntase libre de persuadirme de que las tuplas son una buena idea para los tipos "grandes", diciendo que esto no es así :-)
Para devolver múltiples valores, las tuplas son perfectas si los valores son de tipos incompatibles, pero a algunas personas no les gustan si es posible que la persona que llama los ponga en el orden incorrecto. A algunas personas no les gustan los valores de retorno múltiples, y no quieren alentar su uso haciéndolos más fáciles. Algunas personas simplemente prefieren estructuras con nombre para parámetros de entrada y salida, y probablemente no podrían ser persuadidos con un bate de béisbol para usar tuplas. No tiene en cuenta el sabor.
fuente
Como mucha gente señaló, las tuplas no son tan útiles como otras características.
Los trucos de intercambio y rotación son solo trucos. Son completamente confusos para aquellos que no los han visto antes, y dado que son casi todos, estos trucos son simplemente una mala práctica de ingeniería de software.
Devolver múltiples valores usando tuplas es mucho menos autodocumentado que las alternativas: devolver tipos con nombre o usar referencias con nombre. Sin esta autodocumentación, es fácil confundir el orden de los valores devueltos, si son mutuamente convertibles y no son más sabios.
fuente
No todos pueden usar boost, y TR1 aún no está ampliamente disponible.
fuente
Cuando se usa C ++ en sistemas integrados, la extracción de las bibliotecas Boost se vuelve compleja. Se acoplan entre sí, por lo que el tamaño de la biblioteca crece. Devuelve estructuras de datos o usa paso de parámetros en lugar de tuplas. Al devolver tuplas en Python, la estructura de datos está en el orden y el tipo de los valores devueltos simplemente no es explícito.
fuente
Raramente los ve porque el código bien diseñado generalmente no los necesita; no hay muchos casos en la naturaleza en los que el uso de una estructura anónima sea superior al uso de uno con nombre. Como todo lo que una tupla realmente representa es una estructura anónima, la mayoría de los codificadores en la mayoría de las situaciones simplemente van con lo real.
Digamos que tenemos una función "f" donde un retorno de tupla podría tener sentido. Como regla general, tales funciones suelen ser tan complicadas que pueden fallar.
Si "f" PUEDE fallar, necesita un retorno de estado; después de todo, no desea que las personas que llaman tengan que inspeccionar cada parámetro para detectar la falla. "f" probablemente encaja en el patrón:
Eso no es bonito, pero mira lo fea que es la alternativa. Tenga en cuenta que todavía necesito un valor de estado, pero el código no es más legible y no más corto. Probablemente también sea más lento, ya que incurro en el costo de 1 copia con la tupla.
Otro inconveniente importante está oculto aquí: con "ReturnInts" puedo agregar el retorno de "f" modificando "ReturnInts" SIN ALTERAR LA INTERFAZ de "f". La solución de tupla no ofrece esa característica crítica, lo que la convierte en la respuesta inferior para cualquier código de biblioteca.
fuente
using std::tuple;
y simplemente usartuple
en el código.tuple
hace que el código sea menos legible, no más. La mayoría de los códigos en estos días tienen una gran cantidad de símbolos, yastd::tuple
que al verlos queda a la vista exactamente lo que es.Ciertamente, las tuplas pueden ser útiles, pero como se mencionó, hay un poco de sobrecarga y un obstáculo o dos que debes superar antes de que realmente puedas usarlas.
Si su programa encuentra constantemente lugares donde necesita devolver múltiples valores o intercambiar varios valores, puede valer la pena ir a la ruta de las tuplas, pero de lo contrario a veces es más fácil hacer las cosas de la manera clásica.
En términos generales, no todo el mundo ya tiene instalado Boost, y ciertamente no pasaría por la molestia de descargarlo y configurar mis directorios de inclusión para que trabajen con él solo por sus instalaciones de tupla. Creo que descubrirá que las personas que ya usan Boost tienen más probabilidades de encontrar usos de tuplas en sus programas que los usuarios que no son de Boost, y los migrantes de otros idiomas (Python viene a la mente) tienen más probabilidades de estar molestos por la falta de tuplas. en C ++ que explorar métodos para agregar soporte de tuplas.
fuente
Como un almacén de datos
std::tuple
tiene las peores características tanto de astruct
como de una matriz; todo el acceso se basa en la enésima posición, pero no se puede iterar mediantetuple
unfor
bucle.Entonces, si los elementos en el
tuple
son conceptualmente una matriz, usaré una matriz y si los elementos no son conceptualmente una matriz, una estructura (que tiene elementos nombrados) es más fácil de mantener. (a.lastname
Es más explicativo questd::get<1>(a)
).Esto deja la transformación mencionada por el OP como el único caso de uso viable para las tuplas.
fuente
Tengo la sensación de que muchos usan Boost.Any y Boost.Variant (con algo de ingeniería) en lugar de Boost.Tuple.
fuente