2010-02-25 10 views
4

Je suis en train d'écrire un code de metaprogramming tel que:Héritant hors d'une liste des classes à modèle, lorsqu'ils sont fournis avec la liste des arguments de modèle

  • Héritant de quelque classe foo<c1, c2, c3, ...> résultats en matière d'héritage de key<c1>, key<c2>, key<c3>, ...
  • L'approche la plus simple ne fonctionne pas car vous ne pouvez pas hériter de la même classe vide plus d'une fois.
  • Manipuler la partie "..." n'est pas joli (puisqu'il s'agit de copier-pâtes), mais ça marche.

D'accord, donc, voici la tentative:

template<char c0, typename THEN, typename ELSE> 
struct char_if 
{ 
    typename THEN type; 
}; 
template<typename THEN, typename ELSE> 
struct char_if<0, THEN, ELSE> 
{ 
    typename ELSE type; 
}; 
class emptyClass {}; 


template<char c> class key 
{ 
    char getKey(){return c;} 
}; 

template<char c0, char c1, char c2, char c3, char c4> 
class inheritFromAll 
{ 
    typename char_if<c0, key<c0>, emptyClass>::type valid; 

    class inherit 
     : valid 
     , inheritFromAll<c1, c2, c3, c4, 0>::inherit 
    {}; 
}; 

template<char c1, char c2, char c3, char c4> 
class inheritFromAll<0, c1, c2, c3, c4> 
{ 
    class inherit {}; 
}; 

template<char c0 = 0, char c1 = 0, char c2 = 0, char c3 = 0, char c4 = 0> 
class whatINeedToDo 
    : public inheritFromAll<c0, c1, c2, c3, c4>::inherit 
{ 
    bool success(){return true;} 

}; 

int main() 
{ 
    whatINeedToDo<'A', 'B', 'c', 'D'> experiment; 
    return 0; 
} 

j'avais à l'origine si je pouvais utiliser Boost :: Mpl pour le faire, mais je ne pouvais honnêtement pas comment; Je ne pouvais pas comprendre comment vous passeriez un list<...> sans toujours connaître explicitement la partie ....

Il suffit de faire:

template<> class key<0> {}; 

ne fonctionne pas parce que si j'ai alors plus d'un paramètre 0, je tente d'hériter de la même chose deux fois. (Si vous pouvez penser à une solution de contournement pour cela, cela fonctionnerait aussi).

Je n'ai pas non plus essayé de macros, parce que je pense que je les connais moins que je ne connais la métaprogrammation, donc elles pourraient fonctionner comme une solution.

Des idées?

Éditer: J'ai une mauvaise solution. Je voudrais encore une solution de méta-programmation, pour l'apprentissage, mais la mauvaise solution est la suivante:

template<char c1, char c2, char c3> class inheritFromMany 
    : public key<c1> 
    , public key<c2> 
    , public key<c3> 
{ 

}; 
template<char c1, char c2> class inheritFromMany<c1, c2, 0> 
    : key<c1> 
    , key<c2> 
    { 

    }; 

Edit2: Woof, mais j'ai oublié une partie. J'ai besoin de passer une variable au constructeur de '' key '' - c'est la même chose dans tous les cas, mais c'est nécessaire.

Edit3: Commentaires: Aborder

  • Je ne suis pas attendre à l'utilisateur de soumettre le même caractère plus d'une fois. Si c'était le cas, je voudrais seulement hériter de cette clé une fois - je veux dire, je suppose que je ne l'ai pas mentionné parce que tu ne peux pas faire ça? C'est pourquoi d'autres solutions plus simples ne fonctionnent pas?
  • Le point réel de ceci est que la clé est un wrapper pour un comportement signal/slot (canal). Le canal conserve une liste de rappels, qui n'est en fait que virtual key<ch>::callback. Ainsi, hériter d'une clé vous donne accès au canal de cette clé, permet (ou fait) de fournir un rappel. keyInput<ch1, ch2, ch3,...> est alors une enveloppe pour que, si vous n'avez pas key<ch1>, key<ch2>, key<ch3>
+2

Il vous manque l'élément important de information de la question: qu'est-ce que vous voulez réaliser. Si vous présentez une liste contenant le même élément plus d'une fois, que prévoyez-vous? Hériter de «clé » une seule fois supprimer les doublons? –

Répondre

3

Sans vous dire ce que vous voulez vraiment atteindre, c'est un exercice essentiellement académique ... mais voici une façon comment vous utiliser MPL pour hériter de façon linéaire:

template<class T> struct key { 
    enum { value = T::value }; 
    char getKey() { return value; } 
}; 

template<class Values> struct derivator 
    : mpl::inherit_linearly< 
      Values 
     , mpl::inherit< mpl::_1, key<mpl::_2> > 
     >::type 
{}; 

// usage:  
typedef mpl::vector_c<char, 1,2,3> values; 
typedef derivator<values> generated; 

// or: 
derivator< mpl::vector_c<char, 1,2,3> > derived; 

peut-être que vous pouvez préciser sur cette base ce dont vous avez besoin.Je dois passer une variable au constructeur de '' key '' - c'est la même chose dans tous les cas, mais c'est nécessaire. Voulez-vous dire que vous voulez transmettre un paramètre via la chaîne d'héritage à tous les constructeurs? Alors jetez un oeil aux solutions à this question.


Quant à éviter mpl::vector_c dans l'interface visible, vous pouvez utiliser votre approche précédente et construire en interne que par l'insertion de valeurs non égales à zéro en elle:

template<char c, class S> struct push_char { 
    typedef typename mpl::push_front<S, mpl::char_<c> >::type type; 
}; 

template<class S> struct push_char<0, S> { 
    typedef S type; // don't insert if char is 0 
}; 

template<char c1=0, char c2=0, char c3=0> 
struct char_vector { 
    // build the vector_c 
    typedef 
     typename push_char<c1 
     , typename push_char<c2 
     , typename push_char<c3 
     , mpl::vector_c<char> 
     >::type>::type>::type 
    type; 
}; 

template<char c1=0, char c2=0, char c3=0> 
struct derivator 
    : mpl::inherit_linearly< 
      typename char_vector<c1,c2,c3>::type 
     , mpl::inherit< mpl::_1, key<mpl::_2> > 
     >::type 
{}; 
+0

Est-il possible d'éviter d'utiliser '' mpl :: vector_c'' dans l'utilisation? – Narfanator

+1

Bien sûr, vous pouvez faire de 'derivator' un modèle pseudo variadique, mais vous finissez par reproduire' vector_c' ou similaire (comme avec la plupart des fonctionnalités MPL). Pourquoi devriez-vous exactement? –

+0

On dirait que le bit de clé est le inherit_linearly <_1, 'key<_2> '>? – Narfanator