bar*_*ney 5 c++ lambda templates variadic-templates type-deduction
我想创建一个模板类或函数,它接收 lambda,并将其内部放入 std::function<> Lambda 可以有任意数量的输入参数 [](int a, float b, ...) std:: function<> 应该对应于 lambda 的 operator() 的类型
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){});
}
Run Code Online (Sandbox Code Playgroud)
所以我需要以某种方式提取返回类型和参数包
这里的答案建议在 lambda 的 :: 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.
};
};
Run Code Online (Sandbox Code Playgroud)
但我需要一种方法将 tuple<> 转换回参数包,以创建正确的 std::function<> 实例化
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{});
}
Run Code Online (Sandbox Code Playgroud)
上面的代码应该可以完成您想要的操作。正如您所看到的,主要思想是创建一个整数包。这是相当于可变参数的非类型模板。我不知道有什么技术可以在不调用另一个函数的情况下使用这样的包,因此通常在使用元组的这些情况下,您会看到一个嵌套的“impl”函数来完成所有工作。获得整数包后,您可以在访问元组时扩展它(也适用于获取值)。
在风格上:使用using, not typename,特别是在模板密集的代码中,因为前者也可以为模板别名。并且不要使用该enum技巧来存储不使用空间的静态值;无论如何,编译器都会对此进行优化,并且仅使用static constexpr整数会更清晰。