gpt4 book ai didi

c++ - lambdas 和 std::function 的包装器

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:09:55 25 4
gpt4 key购买 nike

我想创建一个函数,它将 lambda、std::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>());
};

所以我创建了几个 helper 来处理我的问题:

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());
}

它适用于 std::function 和常规函数,但它对 lambda 毫无用处(这意味着每次我想将 lambda 函数作为参数传递时,我必须用 包装它std::function(RET_VAL(ARGS)) 首先)。有没有什么方法可以专门化 function_traits 模板来推断 lambda 参数类型?

最佳答案

我会开始:

template<class...Args, class F>
std::result_of_t<F(Args&&...)>
apply_variant( F&& f, QVariantList& list ){
auto indexer=index_upto<sizeof...(Args)>();
return indexer([&](auto...Is)->decltype(auto){
return std::forward<F>(f)( list.value(Is).value<Args>()... );
};
}

哪里hereindex_upto

现在我们退一步:

template<class...Args, class F>
WrapperFunctionType createWrapper(F&& f){
return [f=std::forward<F>(f)](auto& list)mutable->decltype(auto){
return apply_variant<Args...>( f, list );
};
}
template<class R, class...Args>
WrapperFunctionType createWrapper(std::function<R(Args...)> f){
return [f=std::move(f)](auto& list)mutable->decltype(auto){
return apply_variant<Args...>( f, list );
};
}
template<class R, class...Args>
WrapperFunctionType createWrapper(R(*f)(Args...)){
return [f=std::move(f)](auto& list)mutable->decltype(auto){
return apply_variant<Args...>( f, list );
};
}

现在,这个版本你必须传递你希望用来调用函数对象的类型。

我们可以做一个不明智的:

namespace details{
template<class T>struct tag_t{};
template<class...Args, class R, class U, class F>
WrapperFunctionType createWrapper(tag_t<R(U::*)(Args...)>, F&& f){
return [f=std::forward<F>(f)](auto& list)mutable->decltype(auto){
return apply_variant<std::remove_reference_t<Args>...>( f, list );
};
}
}
template<class F>
WrapperFunctionType createWrapper(F&& f){
using dF=std::decay_t<F>;
using sig_t = details::tag_t<decltype(&dF::operator())>;
return details::createWrapper( sig_t{}, std::forward<F>(f) );
}

或类似的东西。

代码未编译。

关于c++ - lambdas 和 std::function 的包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43463103/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com