从作为模板函数参数传递的 std::function 推导出 return 和参数类型?
Deducing return and parameter type from std::function passed as a template function argument?
我已经四处寻找了一段时间,但找不到我正在寻找的答案 - 可能最接近我的想法。
一句话:是否可以声明一个模板函数,它接受一个std::function
的参数,并为return类型和函数的参数类型推导出模板参数?示例:
//this works to pass the std::function in
template<class T>
void doSomething(std::function<T> f) {
f();
}
//this is more what i am looking for - can R and P be deduced automatically - does not work!
template<class R, class P>
void doSomethingElse(std::function<R(P)> f) {
f();
}
是不是函数签名或者函数类型本身就是一回事,不能"broken"起来?我知道有 decltype
和 std::result_of
,但想不出我该如何在这里使用它们。
另外一点,我如何使用可变参数模板扩展第二个示例以具有多个参数和推导?
template<class R, class P>
void doSomethingElse(std::function<R(P)> f) {
f(P{});
}
会起作用,但只有当您将 std::function
传递给函数并且该函数具有一个非 void 参数时它才会起作用。不过,这是一种限制。你可以使用
template<class R, class... Args, class... Ts>
void doSomethingElse(std::function<R(Args...)> f, Ts&&... args) {
f(std::forward<Args>(args)...);
}
它将接受任何 std::function
及其参数并调用它们,就像您在调用站点中所做的那样。这仍然是有限的,因为调用站点要求您使用 std::function
,因此您不能将任何可隐式转换为 std::function
的内容传递给它。
对于 C++17 和 class template argument deduction (CTAD),这不再是问题。我们可以创建一个接受任何类型的重载,然后使用 CTAD 构造一个 std::function 来为我们填充类型。看起来像
template<class Func, class... Args>
void doSomethingElse(Func&& f, Args&&... args) {
doSomethingElse(std::function{std::forward<Func>(f)}, std::forward<Args>(args)...);
}
template<class R, class... Args, class... Ts>
void doSomethingElse(std::function<R(Args...)> f, Ts&&... args) {
f(std::forward<Args>(args)...);
}
现在任何不是 std::function
的内容都会转到 void doSomethingElse(Func&& f, Args&&... args)
,转换为 std::function
,然后传递给 void doSomethingElse(std::function<R(Args...)> f, Args&&... args)
,这样您就可以使用return 类型和参数类型。
我已经四处寻找了一段时间,但找不到我正在寻找的答案 -
一句话:是否可以声明一个模板函数,它接受一个std::function
的参数,并为return类型和函数的参数类型推导出模板参数?示例:
//this works to pass the std::function in
template<class T>
void doSomething(std::function<T> f) {
f();
}
//this is more what i am looking for - can R and P be deduced automatically - does not work!
template<class R, class P>
void doSomethingElse(std::function<R(P)> f) {
f();
}
是不是函数签名或者函数类型本身就是一回事,不能"broken"起来?我知道有 decltype
和 std::result_of
,但想不出我该如何在这里使用它们。
另外一点,我如何使用可变参数模板扩展第二个示例以具有多个参数和推导?
template<class R, class P>
void doSomethingElse(std::function<R(P)> f) {
f(P{});
}
会起作用,但只有当您将 std::function
传递给函数并且该函数具有一个非 void 参数时它才会起作用。不过,这是一种限制。你可以使用
template<class R, class... Args, class... Ts>
void doSomethingElse(std::function<R(Args...)> f, Ts&&... args) {
f(std::forward<Args>(args)...);
}
它将接受任何 std::function
及其参数并调用它们,就像您在调用站点中所做的那样。这仍然是有限的,因为调用站点要求您使用 std::function
,因此您不能将任何可隐式转换为 std::function
的内容传递给它。
对于 C++17 和 class template argument deduction (CTAD),这不再是问题。我们可以创建一个接受任何类型的重载,然后使用 CTAD 构造一个 std::function 来为我们填充类型。看起来像
template<class Func, class... Args>
void doSomethingElse(Func&& f, Args&&... args) {
doSomethingElse(std::function{std::forward<Func>(f)}, std::forward<Args>(args)...);
}
template<class R, class... Args, class... Ts>
void doSomethingElse(std::function<R(Args...)> f, Ts&&... args) {
f(std::forward<Args>(args)...);
}
现在任何不是 std::function
的内容都会转到 void doSomethingElse(Func&& f, Args&&... args)
,转换为 std::function
,然后传递给 void doSomethingElse(std::function<R(Args...)> f, Args&&... args)
,这样您就可以使用return 类型和参数类型。