Не обязательно понять, что вам нужно.
Но мне кажется, что вам нужно std::bind()
.
В любом случае ... если аргументы для одного вызываемого объекта передаются в Subscribe()
, мне кажется, что Event
больше не должен быть классом шаблона и что std::vector
из std::function
является чем-то следующим образом
private:
std::vector<std::function<void()>> subsV;
Я имею в виду: вектор std::function
типа void()
.
Вы можете заполнить его с помощью следующего метода
template <typename F, typename ... Args>
std::size_t Subscribe (F const & f, Args const & ... as)
{
subsV.emplace_back(std::bind(f, as...));
return subsV.size() - 1u;
}
Заметьте, что с простым вызываемым (не нестатическим методом класса / структуры) вы должны вызывать его, передавая сначала вызываемый, а затем аргументы
auto i1 = e.Subscribe(
[](int, long){ std::cout << "l1" << std::endl; }, 0, 1l);
но, вызывая его нестатическим методом, вы должны сначала передать указатель на метод, затем объект или указатель на объект (работает в обоих случаях) класса и, наконец, аргументы для метода.
foo f;
// ...............................V works with objects
auto i2 = e.Subscribe(&foo::func, f, "string 1");
auto i3 = e.Subscribe(&foo::funv, &f, "string 2");
// ...............................^^ and works with pointers
Для Unsuscribe()
я предлагаю передать индекс подписки (возвращается Subscribe()
void Unsubscribe (std::size_t idx)
{ subsV.at(idx) = nullptr; }
и Trigger()
просто становятся
void Trigger ()
{
for ( auto & sub : subsV )
if ( sub )
sub();
}
Ниже приведен полный пример компиляции (должен работать также с C ++ 11)
#include <vector>
#include <iostream>
#include <functional>
class Event
{
private:
std::vector<std::function<void()>> subsV;
public:
Event() = default;
~Event() = default;
template <typename F, typename ... Args>
std::size_t Subscribe (F const & f, Args const & ... as)
{
subsV.emplace_back(std::bind(f, as...));
return subsV.size() - 1u;
}
void Unsubscribe (std::size_t idx)
{ subsV.at(idx) = nullptr; }
void Trigger ()
{
for ( auto & sub : subsV )
if ( sub )
sub();
}
};
struct foo
{
void func (std::string const & s)
{ std::cout << "foo::func(): " << s << std::endl; }
};
int main()
{
Event e;
foo f;
auto i1 = e.Subscribe(
[](int, long){ std::cout << "l1" << std::endl; }, 0, 1l);
auto i2 = e.Subscribe(&foo::func, f, "string 1");
auto i3 = e.Subscribe(&foo::func, &f, "string 2");
e.Trigger();
e.Unsubscribe(i2);
e.Trigger();
e.Unsubscribe(i1);
e.Trigger();
e.Unsubscribe(i3);
e.Trigger();
}