Шаблон Boost :: Привязка для автоматической обработки нескольких аргументов для функции пользователей
-
29-09-2019 - |
Вопрос
У меня есть класс с функцией «Присоединение», которая принимает функциональный объект и сохраняет его в коллекцию. Сам класс шаблон на функциональной подписи. Что-то вроде этого:
template<class Signature>
class Event
{
public:
void Attach(boost::function<Signature> signature)
{
MySignatures.push_back(signature);
}
private:
std::list<boost::function<Signature>> MySignatures;
};
Чтобы продемонстрировать использование, рассмотрите следующий класс:
class Listening
{
public:
int SomeFunction(int x, int y, int z);
};
Пройти функцию на Listening
в Event
, Мне нужно было написать:
Event<int(int, int, int)> myEvent;
Listening myListening;
myEvent.Attach(boost::bind(boost::mem_fn(&Listening::SomeFunction), &myListening, _1, _2, _3));
Таким образом, вместо этого для каждого случая, которые могут быть склонны к ошибке, я пишу набор макросов следующим образом:
#define EventArgument0(x, y) boost::bind(boost::mem_fn(x), y)
#define EventArgument1(x, y) boost::bind(boost::mem_fn(x), y, _1)
#define EventArgument2(x, y) boost::bind(boost::mem_fn(x), y, _1, _2)
#define EventArgument3(x, y) boost::bind(boost::mem_fn(x), y, _1, _2, _3)
#define EventArgument4(x, y) boost::bind(boost::mem_fn(x), y, _1, _2, _3, _4)
etc.
И тогда я могу написать:
myEvent.Attach(EventArgument3(&Listening::SomeFunction, &myListening));
Что намного проще читать (я думаю). Теперь на мой вопрос: как я могу вместо этого написать:
myEvent.Attach(EventArgument(&Listening::SomeFunction, &MyListening));
Или еще лучше:
myEvent.Attach(&Listening::SomeFunction, &myListening);
, Таким образом, что прикрепление события волшебно связывается правильно с соответствующим количеством аргументов, которые содержатся вu003CSignature> (В этом примере, int(int, int, int)
)? Я открыт для любого шаблона Meta-программирования, которую вы имеете в виду здесь.
Спасибо.
Редактировать: оказывается, мне не нужно boost::mem_fn
Вот, потому что boost::bind
эквивалентно, поэтому в моем макро я могу использовать:
bind(&MyClass::Hello, myClass, _1, _2, _3);
,вместо:
bind(mem_fn(&MyClass::Hello), myClass, _1, _2, _3);
Однако вопрос остается: как пройти &MyClass::Hello
в класс событий и используйте перегрузку шаблона для обработки _1
, _2
, _3
, и т. Д., Подразумеваемые функциональным прототипом, используемым для шаблона Event
класс?
Решение
Перегрузка Attach
Для разного количества параметров в функции члена:
template<typename R,typename T,typename U>
void Attach(R (T::*pmf)(),U* p))
{
Attach(boost::bind(pmf,p));
}
template<typename R,typename T,typename U,typename A1>
void Attach(R (T::*pmf)(A1),U* p))
{
Attach(boost::bind(pmf,p,_1));
}
template<typename R,typename T,typename U,typename A1,typename A2>
void Attach(R (T::*pmf)(A1,A2),U* p))
{
Attach(boost::bind(pmf,p,_1,_2));
}
Если вам нужно обращаться const
Функции членов тоже тогда вам понадобится второй набор перегрузок.
Другие советы
Изготовление Attach()
Шаблон позволит вам делать то, что вы стремитесь. Код становится грязным, но оно позволит вам назвать так, как вы хотите.
template<typename A1>
void Attach(A1 a1);
template<typename A1, typename A2>
void Attach(A1 a1, A2 a2);
template<typename A1, typename A2, typename A3>
void Attach(A1 a1, A2 a2, A3 a3);
template<typename A1, typename A3, typename A4>
void Attach(A1 a1, A2 a2, A3 a3, A4 a4);