Jetez un coup d'œil à la fonction membre virtual std::future<void> DoInvoke ()
de la classe EventMemberImpl
:
#include <future>
#include <functional>
class EventImpl
{
public:
virtual ~EventImpl () = default;
std::future<void> Invoke () { return DoInvoke (); }
private:
virtual std::future<void> DoInvoke () = 0;
};
template <typename... Ts>
EventImpl * MakeEvent (Ts&&... args)
{
class EventMemberImpl : public EventImpl
{
public:
EventMemberImpl (Ts&&... args)
: m_function (std::bind (std::forward<Ts> (args)...))
{
}
protected:
virtual ~EventMemberImpl ()
{
}
private:
virtual std::future<void> DoInvoke ()
{
// MakeEvent has been called with
// a Callable which does not return a future
m_function ();
return std::future<void> ();
// OR
// MakeEvent has been called with a
// Callable which returns a future:
return m_function();
}
// In case is any function... :
std::function<void ()> m_function;
// OR
// ... except when it returns a future:
std::function<std::future<void> ()> m_function;
};
return new EventMemberImpl (std::forward<Ts> (args)...);
}
int foo() { return 5; }
std::future<int> baz () { return std::future<int> (); }
int main ()
{
EventImpl *event1 = MakeEvent(std::forward<decltype (&foo)> (&foo));
EventImpl *event2 = MakeEvent(std::forward<decltype (&baz)> (&baz));
return 0;
}
Ce que je voudrais faire, c'est que lorsque quelqu'un appelle MakeEvent avec une fonction (n'importe quel appelable) comme paramètre qui retourne void (ou presque n'importe quoi d'autre), le corps devrait se comporter exactement comme je l'ai écrit. D'autre part, lorsque la fonction MakeEvent est appelée avec une fonction comme paramètre qui retourne un std::future, alors elle devrait faire des choses différentes.