Тип аргументов лямбда-функции с++
Создаю небольшую систему событий, и если с обычными функциями и методами классов всё определено, то появляется проблема с лямбда-функциями, а именно нужно как-то вытащить типы аргументов из лямбды (и вставить вместо ???). Это вообще возможно как-то сделать?
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>;
Естественно буду рад более красивым и элегантным вариантам