Проблемы с адаптацией функций-членов в Фениксе
Я использую BOOST_PHOENIX_ADAPT_FUNCTION
все время в духе. Я хотел бы иметь возможность адаптировать функции-члены по той же причине. Тем не менее, я получаю ошибки компиляции, если я делаю что-то вроде этого:
struct A { int foo(int i) { return 5*i; }};
BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, &A::foo, 2)
Есть ли простой способ адаптировать функцию-член? Обратите внимание, что я не могу просто сохранить выражение привязки в auto
потому что я на VC2008. Как получается, что это не просто работает, как в bind
а также function
?
Спасибо,
Майк
2 ответа
BOOST_PHOENIX_ADAPT_FUNCTION(RETURN,LAZY_NAME,FUNC,N)
это действительно просто. Это просто создает функтор с шаблонным operator()
это возвращает RETURN
и имеет N
параметры шаблона. В своем теле это просто вызывает FUNC(PARAMETERS...)
, Но &A::foo
не вызывается напрямую, поэтому возникает ваша ошибка. Ты можешь использовать:
BOOST_PHOENIX_ADAPT_FUNCTION(int,AFoo,boost::mem_fn(&A::foo),2)
#include <iostream>
#include <boost/phoenix.hpp>
#include <boost/phoenix/function.hpp>
#include <boost/mem_fn.hpp>
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;
}
Начиная с самого простого:
Как получилось, что он не просто работает как в связывании и функционировании?
Поскольку макрос предназначен для функций, а не функций-членов. Функции указателя на член сильно отличаются от указателей на функции, так что это конец пути.
В вашем примере A::foo
на самом деле не нужно быть методом экземпляра (нестатическая функция-член), поэтому просто добавьте static
(и неявный параметр) и будет сделано:
struct A {
static int foo(int i) {
return 5*i;
}
};
BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, A::foo, 1)
Предположим, однако, что вы хотели иметь нестатическую функцию-член. По этой причине давайте добавим небольшое состояние к A
тип:
struct A {
A(int f) : f_(f) {}
int foo(int i) { return f_*i; }
private:
int f_;
};
Phoenix предлагает следующие подходы для создания ленивых актеров, вызывающих функции-члены:
использовать
->*
оператор. Это приводит к немного неясному синтаксису:A instance(9); int direct = (arg1->*&A::foo)(arg2) (&instance, 7); // direct == 63
В качестве альтернативы, вы можете использовать
bind
выражение (примечание:boost::phoenix::bind
здесь!), что может быть именно тем, что вы искали:int with_bind = bind(&A::foo, arg1, arg2) (&instance, 7);
Теперь, конечно, вы можете назначить ленивый функтор переменной. В этом отношении я могу только рекомендовать BOOST_AUTO
:
BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2));
return afoo(&instance, 2);
Который работает как шарм.
Полный пример C++03
Посмотреть это в прямом эфире на Coliru
struct A {
A(int f) : f_(f) {}
int foo(int i) {
return f_*i;
}
private:
int f_;
};
#include <boost/phoenix.hpp>
#include <boost/phoenix/function.hpp>
#include <cassert>
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);
}