Todo el material que he leído en Curiously Recurring Template Pattern parece una capa de herencia, es decir, Base
y Derived : Base<Derived>
. ¿Qué pasa si quiero dar un paso más?Cómo escribir plantillas curiosamente recurrentes con más de 2 capas de herencia?
#include <iostream>
using std::cout;
template<typename LowestDerivedClass> class A {
public:
LowestDerivedClass& get() { return *static_cast<LowestDerivedClass*>(this); }
void print() { cout << "A\n"; }
};
template<typename LowestDerivedClass> class B : public A<LowestDerivedClass> {
public: void print() { cout << "B\n"; }
};
class C : public B<C> {
public: void print() { cout << "C\n"; }
};
int main()
{
C c;
c.get().print();
// B b; // Intentionally bad syntax,
// b.get().print(); // to demonstrate what I'm trying to accomplish
return 0;
}
¿Cómo puedo volver a escribir el código para compilar sin errores y pantalla
C
B
Usando c.get(). Print() y b.get ().impresión() ?
motivación: Supongamos que tengo tres clases,
class GuiElement { /* ... */ };
class Window : public GuiElement { /* ... */ };
class AlertBox : public Window { /* ... */ };
Cada clase tiene 6 o más parámetros en el constructor, muchos de los cuales son opcionales y tienen valores predeterminados razonables. Para avoid the tedium of optional parameters, el mejor solution es usar el Named Parameter Idiom.
Un problema fundamental con este modismo es que las funciones de la clase de parámetro tienen que devolver el objeto al que están llamadas, aunque algunos parámetros se dan a GuiElement, algunos a Window y algunos a AlertBox. Se necesita una manera de escribir esto:
AlertBox box = AlertBoxOptions()
.GuiElementParameter(1)
.WindowParameter(2)
.AlertBoxParameter(3)
.create();
Sin embargo, esto probablemente fallará porque, por ejemplo, GuiElementParameter (int) devuelve probablemente GuiElementOptions &, que no tiene una función WindowParameter (int).
Esto ha sido asked antes, y la solución parece ser un poco de sabor del Patrón de Plantilla Curiosamente Recurrente. El sabor particular que uso es here.
Es mucho código para escribir cada vez que creo un nuevo Elemento Gui. He estado buscando formas de simplificarlo. Una causa principal de complejidad es el hecho de que estoy usando CRTP para resolver el problema Named-Parameter-Idiom, pero tengo tres capas, no dos (GuiElement, Window y AlertBox) y mi current workaround cuadruplica la cantidad de clases que tengo. (!) Por ejemplo, Window, WindowOptions, WindowBuilderT y WindowBuilder.
Eso me lleva a mi pregunta, en la que estoy esencialmente buscando una manera más elegante de usar CRTP en largas cadenas de herencia, como GuiElement, Window y Alertbox.
¿Desea 'c.get(). Print()' dar salida a "C \ nB \ n" o desea que las líneas que comentó compilen y proporcionen el "B \ n "¿mitad? –
Este último. Editado mi pregunta para ser más claro. – Kyle
Debe indicar para qué quiere esto. Como es la única respuesta posible es: no, no puedes. –