2015-09-20 1 views
4

Alors disons que j'ai une classe avec beaucoup d'arguments de modèle, l'un d'entre eux est la classe dérivée d'utiliser CRTP:Comment éviter boilerplate sur des arguments de modèle lors de l'appel constructeur parent

template <typename Derived, typename A, typename B, typename C, typename D> 
class BaseFoo { 
public: 
    BaseFoo(A& a) {} 
}; 

Et je veux l'hériter:

class DerivedFoo : public BaseFoo<DerivedFoo, Bc, Cc, Dc, Ec> { 
public: 
    DerivedFoo(A& a) : BaseFoo<DerivedFoo, Bc, Cc, Dc, Ec>(a) {} 
}; 

Y a-t-il une astuce pour éviter tout l'argument de modèle explicite?

Il est correct si je dois toujours indiquer Derived en tant qu'arguments de modèle.

+0

pourriez-vous utiliser un 'typedef'? –

+0

Vous voulez dire un typedef dans la classe? Je suppose que oui, mais ce serait écrire la longue liste de modèles deux fois. 'typedef BaseFoo ParentClass;' vous voulez dire cela dans DerivedFoo? En raison de la nécessité d'utiliser le CRTP, je ne sais pas comment faire le typedef en dehors de la classe. – alesegdia

+0

Ne va pas répondre parce que je suppose que si cela était valide, alors quelqu'un aurait déjà mentionné, mais ... pourquoi les modèles variés ne sont pas une solution ici? –

Répondre

6

Utilisez simplement le nom de la classe dérivée et recherchez le nom de la classe de base si la classe de base est dépendante. Si elle n'est pas dépendante, vous pouvez juste nommer la classe de base non qualifiée, puisqu'elle est dans la portée. Aucun besoin de tous les arguments de modèle

class DerivedFoo : public BaseFoo<DerivedFoo, Bc, Cc, Dc, Ec> { 
public: 
    DerivedFoo(A& a) : BaseFoo(a) {} 
}; 

Chaque classe déclare son nom à l'intérieur de lui-même. Non seulement les classes normales, mais aussi les instances de modèle de classe. Donc BaseFoo se réfère à BaseFoo<...> dans sa propre portée et la portée de ses classes dérivées.

+0

Wow, je ne savais pas que c'était possible. Je pensais que je devais énoncer la liste entière des paramètres parce que 'BaseFoo <.......>' est comme une seule classe, et 'BaseFoo' n'était pas statable par ses propres moyens. – alesegdia

+1

@alesegdia: D'habitude et conceptuellement vrai (et ça alors c'est sympa de tomber sur un OP qui comprend ça!), Mais c'est une exception pour plus de commodité. En fait, c'est un exemple typique de la raison pour laquelle c'est autorisé. –

+0

Génial. Il semble que j'ai traversé un exemple de manuel dans la vraie vie. Merci pour l'astuce! – alesegdia

5

Déclarer d'abord DerivedFoo.

class DerivedFoo; 

puis typedef

typedef BaseFoo<DerivedFoo, Bc, Cc, Dc, Ec> OtherFoo; 

également possible avec using

using OtherFoo = BaseFoo<DerivedFoo, Bc, Cc, Dc, Ec>; 

ou si vous ne se soucient pas de devoir parler Derived

template <typename Derived> 
using OtherFoo = BaseFoo<Derived, Bc, Cc, Dc, Ec>; 

class DerivedFoo : public OtherFoo<DerivedFoo> { 
    .... 
}; 
+0

Ou plus alias de modèle moderne avec l'aide? – Alex

+0

Parfait, ça a marché. Il serait bon d'avoir l'alias de modèle moderne en utilisant 'using ', comme l'a déclaré @Alex. – alesegdia

+0

Je vais éditer une fois que je ne suis pas sur un téléphone – Alex