2010-03-01 9 views
8

Je voudrais créer une interface de modèle pour les classes de gestion de données dans mes projets.Transférer la signature de la méthode en tant que paramètre de modèle dans une classe

Je peux écrire quelque chose comme ceci:

template <class T> 
class DataHandler 
{ 
    public: 
     void Process(const& T) = 0; 
}; 

Ensuite, supposons, je définir une classe de cette façon:

class MyClass: public DataHandler<int> 
{ 
    void Process(const int&) { /* Bla-bla */ } 
} 

Maintenant, venez la question, puis-je définir en quelque sorte mon interface de modèle dans la façon dont, en tant que paramètre, il recevra non seulement T, mais la signature entière de la fonction Process().

Je voudrais quelque chose travailler de cette façon:

class MyClass: public DataHandler<void (int&)> 
{ 
    void Process(const int&) { /* Bla-bla */ } 
} 

Est-il possible? Je sais que, par exemple, boost :: signal reçoit les paramètres du template de cette façon, mais si je comprends bien, ils utilisent beaucoup de magie noire là-bas.

Répondre

12

Oui, vous pouvez. Mais en C++ 03, vous êtes obligé de copier/coller du code pour chaque nombre de paramètres (pas trop mal, car ici vous n'aurez pas besoin de surcharges pour const/non-const etc. Le constnes est déjà connu!).

template<typename FnType> 
struct parm; 

template<typename R, typename P1> 
struct parm<R(P1)> { 
    typedef R ret_type; 
    typedef P1 parm1_type; 
}; 

template <class T> 
class DataHandler 
{ 
    typedef typename parm<T>::ret_type ret_type; 
    typedef typename parm<T>::parm1_type parm1_type; 

    public: 
     virtual ret_type Process(parm1_type t) = 0; 
}; 

class MyClass: public DataHandler<void (const int&)> 
{ 
    void Process(const int&) { /* Bla-bla */ } 
}; 

En C++ 0x, vous serez en mesure d'écrire

template <class T> 
class DataHandler; 

template<typename R, typename ... P> 
class DataHandler<R(P...)> 
{ 
    public: 
     virtual R Process(P... t) = 0; 
}; 

class MyClass: public DataHandler<void (const int&)> 
{ 
    void Process(const int&) { /* Bla-bla */ } 
}; 

Combien plus agréable!

+0

Maintenant, la question demeure: combien d'années faudra-t-il jusqu'à ce que nous puissions mettre des modèles variadiques à l'usage quotidien au travail. Savoir combien cela peut être plus simple peut faire mal ... –

+0

Et comment dois-je le changer afin de supporter plus d'un paramètre dans la fonction Process() dans l'interface DataProducer? Je veux dire, je voudrais soutenir quelque chose comme DataHandler Lev

+0

@Lev, je suppose que vous devrez vous spécialiser partiellement DataHandler sur le type de fonction afin d'obtenir la déclaration de la fonction 'Process' juste aussi. 'boost :: function' utilise le préprocesseur pour générer le code nécessaire, mais pour ses propres projets et quelques utilisations, il n'est guère utile (à mon avis) de vous présenter dans ce sujet dont vous n'avez probablement plus besoin par la suite. Donc, il suffit de copier/coller 4 fois et être fait :) –

Questions connexes