问题描述
我想创建一个模板类或函数,该类或函数接收一个lambda并将其内部放入std :: function<>Lambda可以具有任意数量的输入参数[](int a,float b,...)std :: function<>应该与lambda的operator()的类型相对应
I want to create a templated class or function, that receives a lambda, and puts it internally in std::function<>Lambda could have any number of input parameters [](int a, float b, ...) std::function<> should correspond to the lambda's operator()'s type
template <typename T>
void getLambda(T t) {
// typedef lambda_traits::ret_type RetType; ??
// typedef lambda_traits::param_tuple --> somehow back to parameter pack Args...
std::function<RetType(Args...)> fun(t);
}
int main() {
int x = 0;
getLambda([&x](int a, float b, Person c){});
}
所以我需要以某种方式提取返回类型和参数包
So I need to somehow extract the Return Type and Parameter Pack
回答此处建议对lambda的文件使用部分规范:: operator()
Answer here suggests to use partial spec on lambda's :: operator()
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
enum { arity = sizeof...(Args) };
// arity is the number of arguments.
typedef ReturnType result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
// the i-th argument is equivalent to the i-th tuple element of a tuple
// composed of those arguments.
};
};
但是我需要一种方法来将元组<>转换回参数包,以创建适当的std :: function<>实例化
But I need a way to convert tuple<> back to parameters pack, to create a proper std::function<> instantiation
推荐答案
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
using result_type = ReturnType;
using arg_tuple = std::tuple<Args...>;
static constexpr auto arity = sizeof...(Args);
};
template <class F, std::size_t ... Is, class T>
auto lambda_to_func_impl(F f, std::index_sequence<Is...>, T) {
return std::function<typename T::result_type(std::tuple_element_t<Is, typename T::arg_tuple>...)>(f);
}
template <class F>
auto lambda_to_func(F f) {
using traits = function_traits<F>;
return lambda_to_func_impl(f, std::make_index_sequence<traits::arity>{}, traits{});
}
上面的代码应做您想要的.如您所见,主要思想是创建一个整数包.这是等距变量的非类型模板等效项.我不知道可以使用这种包而不调用另一个函数的任何技术,因此通常在具有元组的这些情况下,您会看到一个嵌套的"impl"函数可以完成所有工作.拥有整数包后,可以在访问元组时对其进行扩展(也可以获取值).
The code above should do what you want. The main idea, as you can see, is to create an integer pack. This is the non-type template equivalent of variadics. I don't know of any technique by which you can use such a pack without calling another function, so typically in these situations with tuples you'll see a nested "impl" function that does all the work. Once you have the integer pack, you expand it while accessing the tuple (works for getting the values too).
在风格上,请注意:在模板繁重的代码中使用using
,而不是typename
,尤其是 ,因为前者也可以使用模板别名.而且不要在不使用空格的情况下使用enum
技巧来存储静态值;编译器将以任何方式对其进行优化,而使用static constexpr
整数则更加清晰.
On a stylistic note: use using
, not typename
, especially in template heavy code as the former can alias templates too. And don't use that enum
trick to store a static value without it using space; compilers will optimize this out anyhow and just using a static constexpr
integer is much clearer.
这篇关于如何从通用模板< typename T>中提取lambda的返回类型和可变参数集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!