J’utilise BOOST_PHOENIX_ADAPT_FUNCTION
tout le temps dans Spirit. J’aimerais pouvoir adapter les fonctions des membres pour la même raison. Cependant, je reçois des erreurs de compilation si je fais quelque chose comme ceci:
struct A { int foo(int i) { return 5*i; }}; BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, &A::foo, 2)
Existe-t-il un moyen simple d’adapter une fonction membre? Notez que je ne peux pas simplement stocker une expression de liaison dans une auto
car je suis sur VC2008. Comment se fait-il que cela ne fonctionne pas comme dans bind
et function
?
Merci,
Mike
La BOOST_PHOENIX_ADAPT_FUNCTION(RETURN,LAZY_NAME,FUNC,N)
est vraiment simple. Il crée simplement un foncteur avec un operator()
basé sur un modèle operator()
qui retourne RETURN
et a N
parameters de template. Dans son corps, il invoque simplement FUNC(PARAMETERS...)
. Mais &A::foo
n’est pas directement appelable et votre erreur se produit. Vous pouvez utiliser:
BOOST_PHOENIX_ADAPT_FUNCTION(int,AFoo,boost::mem_fn(&A::foo),2)
Courir sur Coliru
#include #include #include #include struct A { A(int f) : f_(f) {} int foo(int i) { return f_*i; } private: int f_; }; BOOST_PHOENIX_ADAPT_FUNCTION(int,AFoo,boost::mem_fn(&A::foo),2) int main() { using namespace boost::phoenix; using namespace boost::phoenix::arg_names; A instance(5); std::cout << AFoo(arg1,arg2)(&instance, 2) << std::endl; }
En commençant par le plus simple:
Comment se fait-il que cela ne fonctionne pas comme dans bind et function?
Parce que la macro est conçue pour des fonctions, pas des fonctions membres. Les fonctions pointeur vers membre sont très différentes des pointeurs de fonction, c’est donc la fin de la route.
Dans votre exemple, A::foo
n’a pas besoin d’être une méthode d’instance (fonction membre non statique), il suffit donc d’append static
(et un paramètre implicite) et de le faire:
struct A { static int foo(int i) { return 5*i; } }; BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, A::foo, 1)
Supposons cependant que vous souhaitiez avoir la fonction de membre non statique. Pour cette raison, ajoutons un petit état au type A
:
struct A { A(int f) : f_(f) {} int foo(int i) { return f_*i; } private: int f_; };
Phoenix propose les approches suivantes pour créer des acteurs paresseux appelant des fonctions membres:
utilisez l’opérateur ->*
. Cela conduit à une syntaxe légèrement obscure:
A instance(9); int direct = (arg1->*&A::foo)(arg2) (&instance, 7); // direct == 63
alternativement, vous pouvez utiliser une expression bind
(note: boost::phoenix::bind
here!), ce qui pourrait bien être ce que vous cherchiez:
int with_bind = bind(&A::foo, arg1, arg2) (&instance, 7);
Maintenant, bien sûr, vous voudrez peut-être affecter le foncteur paresseux à une variable. À cet égard, je ne peux que recommander BOOST_AUTO
:
BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2)); return afoo(&instance, 2);
Ce qui fonctionne comme un charme.
Voir en direct sur Coliru
struct A { A(int f) : f_(f) {} int foo(int i) { return f_*i; } private: int f_; }; #include #include #include int main() { using namespace boost::phoenix; using namespace boost::phoenix::arg_names; A instance(9); int direct = (arg1->*&A::foo)(arg2) (&instance, 7); int with_bind = bind(&A::foo, arg1, arg2) (&instance, 7); assert(direct == with_bind); BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2)); return afoo(&instance, 2); }