如何在 std::function 的参数中进行可变参数推导?
Posted
技术标签:
【中文标题】如何在 std::function 的参数中进行可变参数推导?【英文标题】:How to do variadic deduction in std::function's parameters? 【发布时间】:2020-09-21 16:22:07 【问题描述】:我尝试实现一个函数 f: (std::function -> int) 它将 1 传递给 input_functor
使用 c++ 可变参数模板。
令 input_functor 为 g。
例如:
如果g是std::function<int(int,int)>
,那么f返回g(1, 1)
。
如果g是std::function<int(int,int,int)>
,那么f返回g(1, 1, 1)
。
如果g是std::function<int(int,int,int,int)>
,那么f返回g(1, 1, 1, 1)
。
#include <functional>
#include <iostream>
template <typename T, typename... Args>
int apply(std::function<int(T, Args...)> func)
auto tmp = [func](Args... args)
return func(1, args...);
;
return apply(tmp);
template <typename T>
int apply(std::function<int(T)> func)
return func(1);
int main()
std::function<int(int, int)> f = [](int a, int b)
return a + b;
;
std::cout << apply(f) << "\n";
return 0;
编译器 (clang++) 错误消息是它无法匹配候选。
main.cpp:9:12: error: no matching function for call to 'apply'
return apply(tmp);
^~~~~
main.cpp:21:18: note: in instantiation of function template specialization 'apply<int, int>' requested here
std::cout << apply(f) << "\n";
^
main.cpp:5:5: note: candidate template ignored: could not match 'function<int (type-parameter-0-0, type-parameter-0-1...)>' against
'(lambda at main.cpp:6:16)'
int apply(std::function<int(T, Args...)> func)
^
main.cpp:13:5: note: candidate template ignored: could not match 'function<int (type-parameter-0-0)>' against '(lambda at main.cpp:6:16)'
int apply(std::function<int(T)> func)
^
1 error generated.
【问题讨论】:
您可能需要显式指定tmp
的类型,您不能从lambda 中推断出std::function
模板参数。或者,显式指定对apply
的递归调用的类型可能更简单
不确定编译器是否能够优化掉所有的 std::functions,代码可能有点慢
【参考方案1】:
您有 2 个问题:
定义顺序:
template <typename T>
int apply(std::function<int(T)> func)
return func(1);
应该放在递归函数之前,以便可见并结束递归。
lambda 不是std::function
,所以不会发生推断
template <typename T, typename... Args>
int apply(std::function<int(T, Args...)> func)
auto tmp = std::function[func](Args... args) // C++17 CTAD
return func(1, args...);
;
return apply(tmp);
DemoC++17
由于您仅限于 C++11,因此您可以创建特征来了解需要哪个 std::function
:
template <typenate T, typename Discarded>
struct always_first
using type = T;
;
template <typenate T, typename Discarded> using always_first_t = typename always_first<T, Discarded>::type;
// possibly directly
// template <typenate T, typename Discarded> using always_first_t = T;
// but old compilers might have some issues with that construct as std::void_t
然后
std::function<int(always_first_t<int, Args>...)> tmp = /* your lambda */;
【讨论】:
以上是关于如何在 std::function 的参数中进行可变参数推导?的主要内容,如果未能解决你的问题,请参考以下文章
Cython:具有自定义参数类型的 std::function 回调
如何返回使用参数包定义的成员函数的 std::function 对象?
如何将 std::function 包装器转换为可变参数函数?