Tout le matériel que j'ai lu sur Curlyly Recurring Template Pattern semble avoir une couche d'héritage, c'est-à-dire Base
et Derived : Base<Derived>
. Et si je veux aller plus loin?Comment écrire des modèles curieusement récurrents avec plus de 2 couches d'héritage?
#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;
}
Comment puis-je réécrire ce code pour compiler sans erreurs et affichage
C
B
En utilisant c.get() impression.() Et b.get ().impression() ?
Motivation: Supposons que j'ai trois classes,
class GuiElement { /* ... */ };
class Window : public GuiElement { /* ... */ };
class AlertBox : public Window { /* ... */ };
Chaque classe prend 6 ou si les paramètres de leur constructeur, dont beaucoup sont optionnelles et ont des valeurs par défaut raisonnables. Pour avoid the tedium of optional parameters, le meilleur solution est d'utiliser le Named Parameter Idiom. Un problème fondamental avec cet idiome est que les fonctions de la classe de paramètre doivent renvoyer l'objet sur lequel elles sont appelées, cependant certains paramètres sont donnés à GuiElement, certains à Window, et d'autres à AlertBox. Vous avez besoin d'une façon d'écrire ceci:
AlertBox box = AlertBoxOptions()
.GuiElementParameter(1)
.WindowParameter(2)
.AlertBoxParameter(3)
.create();
Pourtant, ce échouerait probablement parce que, par exemple, GuiElementParameter (int) retourne probablement GuiElementOptions &, qui ne dispose pas d'une fonction WindowParameter (int).
Cela a été précédemment asked, et la solution semble être une certaine saveur du modèle de modèle curieusement récurrent. La saveur particulière que j'utilise est here.
C'est beaucoup de code à écrire chaque fois que je crée un nouvel élément Gui. J'ai cherché des moyens de le simplifier. Une des principales causes de complexité est le fait que j'utilise CRTP pour résoudre le problème Named-Parameter-Idiom, mais j'ai trois couches et non deux (GuiElement, Window et AlertBox) et mon current workaround quadruple le nombre de classes que j'ai. (!) Par exemple, Window, WindowOptions, WindowBuilderT et WindowBuilder. Cela m'amène à ma question, où je suis essentiellement à la recherche d'une façon plus élégante d'utiliser CRTP sur de longues chaînes d'héritage, telles que GuiElement, Window, et AlertBox.
Voulez-vous 'c.get(). Print()' pour sortir "C \ nB \ n" ou voulez-vous que les lignes que vous avez commentées pour compiler et fournir le "B \ n "moitié? –
Ce dernier. Edité ma question pour être plus clair, je l'espère. – Kyle
Vous devriez indiquer ce que vous voulez pour cela. Comme c'est la seule réponse possible est: non, vous ne pouvez pas. –