I want to create a function which takes a lambda, std::function or regular function as input and wraps it into something like the next function:
void original_function(const int x, float y) {
// do smth ...
}
...
using WrapperType = std::function<void(const QVariantList &)>;
WrapperType original_function_wrapper = [original_function](const QVariantList &vl) {
original_function(vl.value(0).value<int>(), vl.value(1).value<float>());
};
So I created few helpers to deal with my problem:
template<size_t index, typename T>
T unpackFromVariant(const QVariantList &v) {
return qvariant_cast<T>(v.value(static_cast<int>(index)));
};
template<typename T>
struct function_traits;
template<typename Ret, typename... Args>
struct function_traits<Ret(Args...)> {
enum { ArgumentCount = sizeof...(Args) };
using ArgumentTypes = std::tuple<Args...>;
using ReturnType = Ret;
};
template<typename Ret, typename... Args>
struct function_traits<std::function<Ret(Args...)>> {
enum { ArgumentCount = sizeof...(Args) };
using ArgumentTypes = std::tuple<Args...>;
using ReturnType = Ret;
};
template<size_t index, typename T>
struct type_of {
using Type = typename std::remove_reference<decltype(std::get<index>(T()))>::type;
};
using WrapperFunctionType = std::function<void(const QVariantList &)>;
template<typename FT, typename T, size_t... I>
WrapperFunctionType createWrapperImpl(T &&functor, std::index_sequence<I...>) {
return [ff = std::forward<T>(functor)](const QVariantList &vl) {
ff(unpackFromVariant<I, typename type_of<I, typename FT::ArgumentTypes>::Type>(vl) ...);
};
};
template<typename T>
WrapperFunctionType createWrapper(T &&functor) {
using TT = typename std::remove_reference<T>::type;
using FunctionTraits = function_traits<TT>;
using Indices = std::make_index_sequence<FunctionTraits::ArgumentCount>;
return createWrapperImpl<FunctionTraits>(std::forward<T>(functor), Indices());
}
It works well with std::function
and regular functions, but it's useless with lambdas (it means that each time I want to pass lambda-function as argument I must wrap it with std::function(RET_VAL(ARGS))
firstly). Is there any ways to specialize function_traits
template to deduce lambda argument types?