2009-06-13 2 views
0

Je veux être capable de modéliser une classe sur une fonction membre sans avoir besoin de répéter les arguments de la fonction membre - je les dérive automatiquement. Je sais comment faire cela si je nomme la classe en fonction du nombre d'arguments que la fonction prend, mais je veux aussi en déduire cela.Où puis-je trouver, ou comment puis-je créer un mécanisme de wrapper de modèle de fonction membre C++ élégant sans resporting pour booster?

Quelque chose comme ça, bien que cela ne fonctionne pas (au moins dans MSVC 2008 sp1, qui est mon compilateur cible):

class Foo { 
    void func0(); 
    int func2(char *, float); 
}; 

template<typename T> class Wrapper; 

// specialize for zero-argument void func 
template<typename Host, void (Host::*Func)()> class Wrapper<Func> : public Base { 
    ... specialization goes here ... 
}; 

// specialize for two-argument value func 
template<typename Host, typename Ret, typename Arg0, typename Arg1, Ret (Host::*Func)(Arg0, Arg1)> class Wrapper<Func> : public Base { 
    ... specialization goes here ... 
}; 

A travers « Base » Je peux alors traiter ces polymorphically. En fin de compte, je veux l'utiliser pour créer une syntaxe simple wrapper pour un langage de script:

WrapClass<Bar> wrap(
    MemberFunction<&Bar::func0>("func0") + 
    MemberFunction<&Bar::func2>("func2") 
); 

Cependant, cela ne fonctionne pas: la syntaxe de spécialisation est erronée, parce que vous ne pouvez pas correspondre à un pointeur de fonction à un argument typename.

Répondre

1

Je crois que vous devrez adopter une approche des traits, dont la bibliothèque la plus commune est boost, mais si vous voulez éviter le boost, il ne sera pas extrêmement difficile de rouler les vôtres si vous avez limité la portée de la mise en œuvre à juste des fonctions de pointeur-à-membre et les traits sur ceux dont vous avez besoin (modern c++ design est un grand livre expliquant la théorie). Voici comment je le ferais avec boost function_traits et enable_if.

Vous pouvez utiliser un argument de modèle générique, enable_if pour des pointeurs de fonction, utilisez les types de fonction (ou tapez traits) pour retirer les informations dont vous avez besoin:

#include <boost/function_types/function_arity.hpp> 
#include <boost/function_types/is_member_pointer.hpp> 

template<typename T, class Enable = void> class Wrapper; 

/* other specializations... */ 

// For member functions: 
template <class T> 
class Wrapper<T, typename enable_if<is_member_pointer<T> >::type> 
{ /* function_arity<T>::value has the number of arguments */ }; 

Voir this et this

+0

N'ai-je pas mentionné l'exigence "pas de boost"? Je suppose que je ne l'ai pas fait. J'ai une telle exigence, cependant - désolé je ne l'ai pas mentionné. Cependant, je vais plonger dans les en-têtes boost et regarder ce qu'ils ont fait, et imiter le petit sous-ensemble dont j'ai besoin. Je crois que je finirai par devoir définir un template interne de Wrapper qui est spécialisé sur l'arité à son tour. –

+0

Vous avez fait dans le titre. Cependant, mon point est; pour ce faire, vous avez besoin d'une bibliothèque de traits, et le seul que je connaisse est boost. Si vous voulez le faire sans coup de pouce, vous devrez rouler le vôtre ou en trouver un autre. –

1

La bibliothèque standard C++ fournit mem_fun_ref qui fonctionne comme vous le souhaitez, bien qu'elle ne fonctionne que pour les fonctions nullaires et unaires. Bien sûr, vous pouvez utiliser une structure avec tous les paramètres comme votre seul argument.

+0

Malheureusement, je ne peux pas utiliser une structure, car cela ne fonctionne pas avec le cas d'utilisation consistant à lier un langage de script à un groupe de classes existantes de manière simple. Merci pour la suggestion, cependant! –

Questions connexes