¿Cuáles son algunos de los usos prácticos para el de "Curiously Recurring Template Pattern"? El ejemplo "counted class" que se muestra comúnmente simplemente no es un ejemplo convincente para mí.Usos prácticos para el "Patrón de plantilla curiosamente recurrente"
Respuesta
Simulated dynamic binding. Evitar el costo de llamadas a funciones virtuales mientras se retienen algunos de los beneficios jerárquicos es una gran ganancia para los subsistemas donde se puede hacer en el proyecto en el que estoy trabajando actualmente.
Qué tipo de porcentaje de rendimiento y/o ganancias de uso de memoria obtener, por cierto? –
He visto disminuir el tiempo invertido en un cálculo en un orden de magnitud. Este fue, sin duda, un caso de esquina muy inusual, generalmente es mucho menos dramático. Las ganancias de uso de memoria son una proporción insignificante del uso general de la memoria para nosotros. – moonshadow
No veo cómo se puede usar. Polymorhpishm funciona utilizando un puntero de clase base para llamar a los métodos de clase derivados según el tipo de clase derivada. Sin embargo en el código CRTP todavía tiene que plantilla
Generalmente se usa para patrones de tipo polimórfico en los que no es necesario que pueda elegir la clase derivada en tiempo de ejecución, solo en tiempo de compilación. Esto puede ahorrar la sobrecarga de la llamada de función virtual en tiempo de ejecución.
@Greg: ¿puedes dar un ejemplo de código? before: [[clase B {virtual void f() = 0; void g() {.. f(); ...}}; clase D: B {void f();};]] después de [[plantilla
Parece una especie de C macro: aprovecha que la macro no se compila en el momento de la definición, sino en el momento del uso.
#define CALL_THE_RIGHT_FOO foo()
archivo A:
static void foo() {
// do file A thing
}
...
CALL_THE_RIGHT_FOO
...
archivo A:
static void foo() {
// do file B thing
}
...
CALL_THE_RIGHT_FOO
...
El patrón de uso de la plantilla que estás describiendo nos permite hacer "llamamos a la derecha foo" en la plantilla padre, posponiendo la definición de qué exactamente es el foo correcto hasta que se crea una instancia de la plantilla. Excepto en este caso, es la distinción entre ClassA :: foo y ClassB :: foo en función del valor de T en Parent.
También es especialmente útil para mixins (me refiero a las clases heredadas para proporcionar funcionalidad) que ellos mismos necesitan saber en qué tipo están operando (y por lo tanto deben ser plantillas).
En efectiva C++, Scott Meyers proporciona como un ejemplo una plantilla de clase NewHandlerSupport <T>. Esto contiene un método estático para anular el nuevo controlador para una clase en particular (de la misma manera que std :: set_new_handler lo hace para el operador predeterminado new) y un operador nuevo que usa el controlador. Para proporcionar un manejador por tipo, la clase padre necesita saber en qué tipo está actuando, por lo que debe ser una plantilla de clase. El parámetro de la plantilla es la clase hija.
que realmente no podía hacer esto sin CRTP, ya que se necesita la plantilla NewHandlerSupport deberían ejecutarse por separado, con un miembro de datos estática independiente para almacenar el new_handler actual, por cada clase que lo utiliza.
Obviamente, el ejemplo completo es extremadamente no seguro para subprocesos, pero ilustra el punto.
Meyers sugiere que se podría pensar en CRTP como "Hágalo por mí". Yo diría que este es generalmente el caso para cualquier mixin, y CRTP se aplica en el caso donde se necesita una plantilla mixin en lugar de solo una clase mixin.
El CRTP se vuelve mucho menos curioso si se tiene en cuenta que el tipo de subclase que se pasa a la superclase solo se necesita en el momento de la expansión del método. Entonces todos los tipos están definidos. Solo necesita que el patrón importe el tipo de subclase simbólica en la superclase, pero es solo una declaración directa (como todos los tipos de parámetros formales formales son por definición) en lo que se refiere a la superclase.
Utilizamos en una forma algo modificada, pasando la subclase en una estructura de tipos de rasgos a la superclase para hacer posible que la superclase devuelva objetos del tipo derivado. La aplicación es una biblioteca de cálculo geométrico (puntos, vectores, líneas, recuadros) donde toda la funcionalidad genérica se implementa en la superclase, y la subclase solo define un tipo específico: CFltPoint hereda de TGenPoint. También CFltPoint existía antes de TGenPoint, por lo que la creación de subclases era una forma natural de refactorizar esto.
@QBizZ: ¿Sabe que esto también podría implementarse mediante funciones virtuales? Una función virtual que devuelve un puntero a una clase base puede devolver un puntero a una clase derivada dentro de la clase derivada –
¿Está hablando de tipos de devolución co-variante? ¿Dónde una anulación de método virtual puede devolver un puntero (o referencia) a una clase derivada del tipo de retorno original en la clase base? Si es así, entonces soy consciente de esto. Pero para mí es algo diferente ya que la interfaz define el contrato con la clase base. No hay ningún método (o cualquier otro identificador) al que pueda acceder la clase base que no se haya visto en alguna definición. Mientras está en el CRTP, la clase base puede llamar a métodos en una subclase que ni siquiera se han definido en el punto de llamada. Esto sucede en el punto de ejemplificación. – QBziZ
Para un uso de biblioteca en el mundo real de CRTP, mire ATL y WTL (wtl.sf.net). Se usa ampliamente allí para el polimorfismo en tiempo de compilación.
- 1. Curiosamente recurrente plantilla - variación
- 2. ¿Puedo usar el Patrón de Plantilla Curiosamente Recurrente aquí (C++)?
- 3. ¿Usos prácticos para tipos estructurales?
- 4. Usos prácticos de TypedReference
- 5. jQuery .each() - ¿Usos prácticos?
- 6. Usos prácticos de MethodRental Class?
- 7. Curiosamente recurrentes patrón de plantilla y genéricos limitaciones (C#)
- 8. jQuery.map - ¿Usos prácticos para la función?
- 9. ¿Usos prácticos de serialización de objetos?
- 10. algunos usos prácticos de mem_fn & bind
- 11. ¿Cuáles son los usos prácticos de Factory Method Pattern?
- 12. Comportamiento explícito del constructor de copias y usos prácticos
- 13. ¿Cuáles son los usos prácticos de un constructor protegido?
- 14. Usos prácticos de un tipo dinámico en Scala
- 15. ¿Cuáles son los usos prácticos del módulo (%) en la programación?
- 16. ¿Cuáles son algunos usos prácticos para las variables const const en C?
- 17. ¿Cuáles son algunos usos interesantes/prácticos para matrices con tres o más dimensiones?
- 18. clase X: X <T> {} patrón en C# --- ¿para qué se utiliza?
- 19. ¿Ejemplos de usos comunes y prácticos de eventos de burbujeo y captura?
- 20. Ejemplos prácticos de uso de NLTK
- 21. Usos creativos para el control de versión
- 22. ¿Cuáles son algunos usos de los parámetros de plantilla de plantilla en C++?
- 23. Diferencias entre el patrón de generador y el método de plantilla (constructor vs plantilla)
- 24. usos para MapAll (// @)
- 25. Usos de 'para' en Java
- 26. Objective-C - ¿Patrón de métodos de plantilla?
- 27. Consejos prácticos para depurar la recurrencia profunda?
- 28. Wake bloquea el servicio de Android recurrente
- 29. Límites prácticos de ElasticSearch + Cassandra
- 30. Eclipse recurrente colgando
También eche un vistazo a esto para un ejemplo práctico http://stackoverflow.com/questions/10374650/curiously-recurring-template-variation/10374754#10374754 – Ghita