library - C++: ¿Alternativa a STL y Boost?
get boost (8)
Esto evita la redundancia para los escritores de la biblioteca, pero es doloroso para los usuarios de la biblioteca.
No estoy de acuerdo con esta premisa en absoluto. E incluso si lo hiciera, es una gran generalización general que no se aplica a todos los usuarios de la biblioteca. Pero esta es una declaración subjetiva de todos modos, así que la ignoraré.
¿Existen alternativas de C ++ a STL / Boost que ofrezcan tales contenedores en un sabor más tradicional orientado a objetos?
...
Los contenedores deben tener métodos que permitan manipularlos directamente. (Por ejemplo, llamando a vector.sort () en lugar de ordenar (vector.begin (), vector.end ()).
Por supuesto. Simplemente haga sus propios contenedores que tengan los contenedores estándar como miembros de datos y delegue las llamadas a ellos y a los algoritmos según sea necesario a través de las funciones de los miembros. Es bastante trivial de implementar:
template<typename T>
class MyVector
{
public:
void sort()
{
std::sort(vec.begin(), vec.end());
}
// ...
private:
std::vector<T> vec;
};
No hay nada en C ++ que le impida hacer algo como esto, irónicamente, gracias a la naturaleza de paradigma múltiple de C ++ con la que parece no estar de acuerdo.
Probablemente pueda usar private
herencia private
y las declaraciones si prefiere no escribir las funciones de envoltura.
STL / Boost hace que sea un dolor derivar de sus contenedores y extenderlos.
Eso es porque se supone que no debes derivar de ellos. La forma correcta es utilizar la composición, como el fragmento de código que presenté anteriormente.
C ++ es un lenguaje de múltiples paradigmas y STL y Boost están diseñados para el paradigma funcional del lenguaje. STL se compone de contenedores (para contener datos), iteradores (para acceder a datos) y algoritmos (funciones para manipular datos). Las funciones de algoritmo se aplican en contenedores mediante el uso de iteradores. Como efecto secundario, estos métodos no forman parte de las clases de contenedor, sino que están completamente separados. (Esto evita la redundancia para los escritores de la biblioteca, pero es doloroso para los usuarios de la biblioteca).
¿Existen alternativas de C ++ a STL / Boost que ofrezcan tales contenedores en un sabor más tradicional orientado a objetos? Estoy buscando cadenas, vectores, listas enlazadas, mapas, árboles, tablas hash y demás. Los contenedores deben ser fáciles de heredar y extender. En comparación, extender las clases de STL / Boost es una muy mala idea y esto es por diseño de sus diseñadores.
PD: Por favor, no use el espacio de respuesta a continuación para pontificar las ventajas de STL / Boost. ¡Soy muy consciente de ellos! :-)
¿Por qué no usar gráficos en lugar de contenedores STL y adjuntar lo que necesita en nodos o bordes? Pueden imitar cualquier contenedor de STL (¿Me equivoco?). Puede iterar fácilmente sobre nodos o bordes (DFS, BFS) y en el camino puede hacer lo que quiera con los datos adjuntos en nodos y bordes. Fácil mezcla de algoritmo e iterador, ¿no es así?
Eche un vistazo al enfoque de Qt4 , siempre he sido un fanático de él.
actualizado el enlace.
Llegar un poco tarde a esta fiesta Y sé que el OP solicita específicamente no "pontificar", ya que ellos ya saben sobre el STL, sin embargo ...
Hay una vieja entrevista del Dr. Dobbs con Alex Stepanov, un pionero en la programación genérica y uno de los principales contribuyentes a la STL. Es muy instructivo de varias maneras, especialmente para abordar la cuestión de por qué no se utilizan más técnicas estándar de OO en la STL. Destaca un párrafo:
Incluso ahora, la herencia de C ++ no es de mucha utilidad para la programación genérica. Vamos a discutir por qué. Muchas personas han intentado usar la herencia para implementar estructuras de datos y clases de contenedores. Como sabemos ahora, hubo pocos intentos de éxito, si es que hubo alguno. La herencia de C ++ y el estilo de programación asociado con ella están dramáticamente limitados. Es imposible implementar un diseño que incluya algo tan trivial como la igualdad al usarlo. Si comienza con una clase base X en la raíz de su jerarquía y define un operador de igualdad virtual en esta clase que toma un argumento del tipo X, entonces derive la clase Y de la clase X. ¿Cuál es la interfaz de la igualdad? Tiene igualdad que compara Y con X. Usando animales como ejemplo (las personas OO aman a los animales), definen a los mamíferos y derivan jirafas de los mamíferos. Luego define un compañero de función miembro, donde el animal se aparea con el animal y devuelve un animal. Luego derivas una jirafa de un animal y, por supuesto, tiene una función donde la jirafa se aparea con un animal y devuelve un animal. Definitivamente no es lo que quieres. Mientras que el apareamiento puede no ser muy importante para los programadores de C ++, la igualdad es. No conozco un solo algoritmo donde no se use la igualdad de algún tipo.
Para aquellos que prefieren una respuesta de Java a este mismo enigma, Josh Bloch se esfuerza por señalar los mismos puntos en Effective Java, Item 8: Obedezca el contacto general al anular.
Es un buen capítulo, con un buen ejemplo sobre cómo tratar de preservar el contrato de iguales al mismo tiempo que se extiende una clase de puntos simple con color agregado: una clase de ColorPoint. Continúa demostrando que hay una limitación fundamental de la POO: no hay manera de extender una clase instanciable Y agregar un componente de valor mientras se preserva el contrato igual .
Por supuesto, la declaración de Bloch se expresa de manera más sucinta, pero ambas (correctamente) sacan las mismas conclusiones. La principal diferencia es que Java es (era) un lenguaje "puro OO": todo debe residir en una clase, incluso aquellas cosas como los algoritmos, que no son objetos naturales.
Y creo que Bloch puede ser sensible a este problema porque lo ha visto fallar espectacularmente en la biblioteca de Java: la pila heredada de Vector es un ejemplo de un problema de diseño notable en Java.
Un poco más tarde en la entrevista, Stepanov continúa diciendo:
Al principio, participé en varias discusiones en los laboratorios Bell sobre el diseño de plantillas y argumenté de manera bastante violenta con Bjarne que él debería hacer las plantillas de C ++ lo más cerca posible de los genéricos de Ada. Creo que discutí tan violentamente que él decidió no hacerlo. Me di cuenta de la importancia de tener funciones de plantilla en C ++ y no solo clases de plantilla, como algunas personas creían. Sin embargo, pensé que las funciones de la plantilla deberían funcionar como los genéricos de Ada, es decir, que se deberían instanciar explícitamente. Bjarne no me escuchó y diseñó un mecanismo de función de plantilla donde las plantillas se crean instancias de manera implícita utilizando un mecanismo de sobrecarga. Esta técnica en particular se volvió crucial para mi trabajo porque descubrí que me permitió hacer muchas cosas que no eran posibles en Ada. Veo este diseño particular de Bjarne como una obra maravillosa y estoy muy feliz de que no haya seguido mi consejo.
Lo que Dilawar declaró es en realidad la solución para todas sus necesidades de contenedores.
Use Boost :: graph o una implementación similar. Puede usarlo [eso es lo que hago] como un sistema de gestión de objetos.
En cuanto a la crítica de STL, es solo una cuestión de gustos y no de objeciones técnicas. Estos existen, pero no a este nivel.
Muchas (¡la mayoría!) Bibliotecas antiguas para C ++ utilizaban contenedores que se parecían mucho más a los que se usan en cosas como Java y C #.
Algunos ejemplos de tales bibliotecas incluyen COOL , ET++ , la Biblioteca de clases NIH y Rogue Wave Tools.h ++ .
Dos puntos:
- A lo sumo, estas son una fuente de inspiración. Estoy bastante seguro de que han pasado al menos 10 años (ya menudo más o menos 20) desde que alguno de ellos se ha actualizado. No hay prácticamente ninguna posibilidad de que alguno de ellos compile con un compilador razonablemente actual.
- Quiero dejar constancia de que estoy proporcionando enlaces a estos solo en respuesta a una pregunta muy específica. Lo más seguro es que no recomiendo que uses ninguno de los códigos anteriores, ni recomiendo que los uses como inspiración.
Para estar seguro de que estoy claro aquí, al menos IMO:
- Las alegaciones en su pregunta son absolutamente falsas.
- ¡Lo que estás tratando de hacer es completamente loco!
- Estás perdiendo tu tiempo.
- Escribir código de esta manera es una muy, muy mala idea. ¡Solo di no!
- Si insistes en hacer esto, te convertirás en un paria.
- Incluso los no programadores que no entienden bien por qué, comenzarán a odiarte intensamente.
- Tu perro usará tus zapatos y cama como su inodoro.
Estás sólo en esto. ¡Usted ha sido advertido!
Subtítulos cerrados para personas con problemas de humor: por supuesto, algo de eso está destinado a ser humorístico, aunque es una idea realmente pésima.
STL y Boost están tan orientados a los objetos como puedes obtener.
Para todos los propósitos teóricos, la función miembro y una función libre sobrecargada en el primer argumento son la misma cosa. Se comportan de manera muy similar en la práctica, incluso para la herencia, por lo que en C ++ realmente debería considerar que las funciones libres que toman (posiblemente const) la referencia como primer argumento son los métodos de su primer argumento.
La ventaja de las funciones gratuitas es que se pueden definir para la clase existente, lo que le permite agregar una interfaz a la clase existente. Es por eso que STL y especialmente boost los usan tanto. La principal ventaja de las funciones miembro es que pueden ser virtuales (¡pero los métodos virtuales deberían ser privados de todos modos!)
No desea extender las colecciones por derivación. En general, no desea extender nada por derivación a menos que sea una clase base abstracta específicamente diseñada para ello. Vea esta pregunta sobre las ventajas de la composición sobre la herencia .
Te diriges al camino equivocado. Si quieres programar en Java entonces programa en Java. Si programa en C ++, entonces programe como lo hacen los programadores de C ++. Siempre nade con la corriente, nunca en contra.