Je voudrais comprendre s'il est possible d'utiliser une classe imbriquée d'une classe CRTP feuille dans la classe CRTP de base. L'exemple ci-dessous illustre le problème.CRTP - visibilité du type d'une classe feuille imbriquée
#include <iostream>
using namespace std;
template<class T>
class A
{
protected:
T* asLeaf(void)
{return static_cast<T*>(this);}
T const* asLeaf(void) const
{return static_cast<T const*>(this);}
public:
struct Inner
{int a = 10;};
void dispInner(void) const
{std::cout << asLeaf()->inner.a << std::endl;}
// I would like to use T::Inner in this class, e.g.
// typename T::Inner mvInnerA;
// However, I understand that it is not possible to
// use it in the form that is stated above. Thus,
// I am looking for any possible workarounds.
};
class B: public A<B>
{
public:
struct Inner: public A<B>::Inner
{int b = 20;};
protected:
friend A<B>;
B::Inner inner;
public:
void dispInner(void) const
{
A<B>::dispInner();
std::cout << asLeaf()->inner.b << std::endl;
}
};
int main()
{
B b;
b.dispInner();
return 0;
}
EDIT
Je voudrais donner quelques commentaires supplémentaires sur la base des commentaires que je reçois:
- Je suis conscient que je ne sois pas en utilisant des pratiques de conception adéquates . En particulier, on peut se demander si
A
devrait être au courant de l'existence deinner
. Cependant, je voudrais définir un objetinner
du typeB::Inner
dansA
au lieu de fournir la définition deinner
dansB
et l'utiliser dansA
. - Je suis conscient que je ne peux pas expédier déclarer
B
et/ouB::Inner
et des raisons pour lesquelles cela ne peut pas être fait. Ainsi, techniquement, le problème de conception n'a pas de solution. Cependant, je suis à la recherche d'une solution de contournement réalisable.
Je l'ai déjà examiné plusieurs solutions alternatives:
- L'une des solutions possibles possibles est de ne pas faire des tentatives pour « définir »
B::Inner inner
dansA
et utiliser les fonctions membres deA
pour fournir la fonctionnalité permet de modifier la partieA<B>::Inner
deB::Inner inner
. - Une autre solution possible consiste à définir explicitement les classes
A<B>::Inner
etB::Inner
(c'est-à-dire pas comme des classes imbriquées). Cependant, je préférerais éviter cela, parce que, par sa conception, on ne prévoit pas que toutes les classes qui ne dérivent pas deA
devront interagir avecA<B>::Inner
ou les classes qui dérivent deA<B>::Inner
Les deux solutions que je ont présenté peut être acceptable. Cependant, je cherche des alternatives réalisables.
La règle générale est que votre classe de base ne doit pas connaître son enfant, vous présentez des dépendances cycliques qui sont mauvaises – lapinozz
@lapinozz c'est pourquoi il utilise le CRTP (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) et rien de mal avec ça. –
@lapinozz - Vous pensez en termes de polymorphisme dynamique, qui est complètement orthogonal au polymorphisme statique avec le CRTP. Les mêmes "règles" ne s'appliquent pas nécessairement. – StoryTeller