Тип аргументов лямбда-функции с++

Создаю небольшую систему событий, и если с обычными функциями и методами классов всё определено, то появляется проблема с лямбда-функциями, а именно нужно как-то вытащить типы аргументов из лямбды (и вставить вместо ???). Это вообще возможно как-то сделать?

template<class... _Args>
class AbstractEventHandler {
public:
    virtual void call(_Args... args) = 0;
    virtual ~AbstractEventHandler() {}
protected:
    AbstractEventHandler() {}
};

template<class _HandleFunction>
class LambdaEventHandler : 
    public AbstractEventHandler<???>
{
private:
    _HandleFunction _handle_function;
public:
    LambdaEventHandler(const _HandleFunction& handle_function) : _handle_function(handle_function) {}
    LambdaEventHandler(_HandleFunction&& handle_function) : _handle_function(handle_function) {}
public:
    virtual void call(???) override {
        _handle_function(???);
    }
};

template<class _HandleFunction>
LambdaEventHandler(_HandleFunction)->LambdaEventHandler<_HandleFunction>;

template <class... _Args>
class Event {
private:
    std::list<AbstractEventHandler<_Args...>*> _handlers;
public:
    Event& operator += (AbstractEventHandler<_Args...>& handler) {
        _handlers.push_back(&handler);
        return *this;
    }
    void operator()(_Args... args) {
        for (auto&& handler : _handlers) {
            handler->call(args...);
        }
    }
};

Ответы (1 шт):

Автор решения: Кирилл Чуркин

Собственно мне удалось решить проблему следующим образом

Для начала сделаем пак типов

namespace {
    template<class... _Args>
    struct pack {};
}

Будем использовать его в немного переделанном классе LambdaEventHandler

template<class... Unused>
class LambdaEventHandler;

template<class _HandleFunction, class... _Args>
class LambdaEventHandler<_HandleFunction, ::pack<_Args...>> :
    public AbstractEventHandler<_Args...>
{
private:
    _HandleFunction _handle_function;
public:
    LambdaEventHandler(const _HandleFunction& handle_function) : _handle_function(handle_function) {}
    LambdaEventHandler(_HandleFunction&& handle_function) : _handle_function(handle_function) {}
public:
    virtual void call(_Args... args) override {
        _handle_function(args...);
    }
};

Далее нужно создать метафункцию, которая вытащит этот пак из std::function

namespace {
    template<class... _Args>
    struct get_function_args;

    template<class... _Args>
    struct get_function_args<std::function<void(_Args...)>> {
        using args_pack = pack<_Args...>;
    };
}

Далее нам нужно только определение функции, которая вернёт нам std::function, выглядит глупо, но надо, без неё не вытащить std::function с шаблонными параметрами

template<class... Args>
auto to_function(std::function<void(Args...)>)->std::function<void(Args...)>;

И последнее это модифицированный deduction guide для LambdaEventHandler

template<class _HandleFunction>
LambdaEventHandler(_HandleFunction handle_function)->LambdaEventHandler < _HandleFunction, typename ::get_function_args<decltype(to_function(std::function(handle_function)))>::args_pack>;

Естественно буду рад более красивым и элегантным вариантам

→ Ссылка