Adding support for one-to-many to our delegate

Currently, our wrappers store an instance to each type. This approach is often used with type erasure, but in our case, it prevents the ability to create many delegates for the same object (that is, no support for one-to-many). To fix this, we will store a pointer to an object in our wrappers instead of the object itself, as follows:

template<
typename T,
typename RET,
typename... ARGS
>
class wrapper :
public base<RET, ARGS...>
{
const T *m_t{};
RET (T::*m_func)(ARGS...);

public:

wrapper(const T *t, RET (T::*func)(ARGS...)) :
m_t{t},
m_func{func}
{ }

RET func(ARGS... args) override
{
return std::invoke(m_func, m_t, args...);
}
};

As shown in the preceding, the only change we have made is we store a pointer to the object we are wrapping instead of the object itself, which also means we need to initialize this pointer in our constructor. To use this new wrapper, we must modify our delegate constructor as follows:

    template<typename T>
delegate(const T *t, RET (T::*func)(ARGS...)) :
m_wrapper{
std::make_unique<wrapper<T, RET, ARGS...>>(t, func)
}
{ }

This, in turn, means we must update our user-defined type deduction guides as follows:

template<
typename T,
typename RET,
typename... ARGS
>
delegate(const T *, RET(T::*)(ARGS...)) -> delegate<RET(ARGS...)>;

With these modifications, we can now create our delegates as follows:

int main(void)
{
spiderman s;
captain_america c;

std::array<delegate<bool(int, int)>, 2> heros {
delegate(&s, &spiderman::attack),
delegate(&c, &captain_america::attack)
};

for (auto &h : heros) {
std::cout << h(0, 42) << ' ';
}

return 0;
}

As shown in the preceding, the delegate takes a pointer to each object, which means we can create as many of these delegates as we wish, including the ability to create delegates to other member function pointers if needed.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset