Шаблон Boost :: Привязка для автоматической обработки нескольких аргументов для функции пользователей

StackOverflow https://stackoverflow.com/questions/3521608

Вопрос

У меня есть класс с функцией «Присоединение», которая принимает функциональный объект и сохраняет его в коллекцию. Сам класс шаблон на функциональной подписи. Что-то вроде этого:

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);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top