2012-12-09 1 views
2

Supposons que vous ayez une méthode de modèle qui prend un pointeur vers une méthode de n'importe quel type. Dans ce modèle, existe-t-il un moyen de transformer l'argument template, qui est un type de pointeur de méthode (void(A::*)() par exemple), en un type de pointeur de fonction avec le même type et les mêmes paramètres, mais sans les informations de classe (void(*)())?Comment faire pour transformer les types de pointeur de méthode en types de pointeur de fonction

J'ai regardé le <type_traits> header, mais n'ai rien trouvé qui m'aiderait.

+0

@Xeo Merci! Je le marquerais comme une réponse, mais vous avez seulement posté un commentaire :) –

+0

Il était incomplet et supposé C++ 11, mais je l'ai étoffé dans une réponse maintenant. – Xeo

Répondre

4

Une façon simple en C++ 11 est une spécialisation partielle avec un modèle variadique:

template<class PMF> struct pmf_to_pf; 

template<class R, class C, class... Args> 
struct pmf_to_pf<R (C::*)(Args...)>{ 
    using type = R(*)(Args...); // I like using aliases 
}; 

Notez que vous avez besoin d'une spécialisation séparée partielle pour const membres-fonctions (et théoriquement pour les ref-qualified aswell):

template<class R, class C, class... Args> 
struct pmf_to_pf<R (C::*)(Args...) const>{ 
    using type = R(*)(Args...); 
}; 

Avec cv-qualifiés ({nil,const}, {nil,volatile}) et ref-qualificatifs ({nil, &, &&}), vous avez un total de 2*2*3 == 12 spécialisations partielles pour fournir . Vous pouvez normalement omettre les qualifications de volatile, en réduisant le total à "juste" 6. Puisque la plupart des compilateurs ne supportent pas les qualificatifs de fonction-ref, vous en avez vraiment besoin de 2, mais soyez conscient du reste.


Pour 03 C++ (compilateurs aka sans modèles variadique), vous pouvez utiliser le formulaire non variadic suivant:

template<class PMF> struct pmf_to_pf; 

template<class Sig, class C> 
struct pmf_to_pf<Sig C::*>{ 
    typedef Sig* type; // 'Sig' is 'R(Args...)' and 'Sig*' is 'R(*)(Args...)' 
}; 

Bien que cela ne fonctionne pas tout à fait avec des qualificatifs de cv, depuis Je pense que C++ 03 n'a pas permis les signatures qualifiées cv (par exemple R(Args...) const) sur lesquelles vous pourriez vous spécialiser partiellement pour supprimer le const.


† Le {...} représentent un ensemble d'une certaine qualification, avec nil représentant l'ensemble vide. Exemples:

  • void f() const& seraient {const}, {nil}, {&}
  • void f() && serait {nil}, {nil}, {&&}

Et ainsi de suite.

+0

Je m'attendrais 'using using type = R (*) (C *, Args ...);' Suis-je manque quelque chose? Peu importe, je relis l'OP, c'est probablement pour la méta-programmation seulement – sehe

+0

@sehe: Eh bien, c'est comme ça que j'ai interprété la question. Si OP voulait l'argument 'C *', c'est une solution facile après tout. – Xeo

Questions connexes