使用参数包将lambda转换为std :: function [英] Cast lambda to std::function with parameter pack
问题描述
关于SO的几个问题与将lambda转换为 std :: function
s有关,但我还没有看到使用参数包作为参数列表的那个问题。在我的g ++版本(7.1.1-4)上,这似乎已损坏,可能只是不受支持。那么这是合法的c ++ 17(按标准)吗?如果不是,为什么?
There are several questions on SO that relate to casting lambdas to std::function
s, but I have yet to see one that uses a parameter pack for the argument list. This seems broken on my version of g++ (7.1.1-4), and possibly it's just not supported. So is this legal c++17 (by the standard)? If not, why?
#include <functional>
template <typename TReturn, typename ... TArgs>
void Functor(std::function<TReturn (TArgs...)> f) {}
int main(int argc, char * argv[]) {
auto x = [] (int a, int b) { return a * b; };
Functor<int, int, int>(x);
return 0;
}
上面的代码无法编译,因为它无法进行类型推断。显然以 std :: function< int(int,int)>
显式键入 x
而不是使用 auto
使错误消失。但这不允许我将r值传递给 Functor
。我也不想通过为函数类型使用另一个模板参数来释放任何类型安全性。
The code above won't compile because it fails type deduction. Obviously explicitly typing x
as std::function<int (int, int)>
instead of using auto
makes the error go away. But that doesn't allow me to pass an r-value to Functor
as I would like. I would also like to not loose any type-safety by using another template parameter for the function type.
我真正不明白的是,为什么上面的代码无法可以编译,但以下代码可以正常工作:
What I really don't understand is why the above code fails to compile, but the below code is fine and works:
#include <functional>
template <typename TReturn, typename TArgA, typename TArgB>
void Functor(std::function<TReturn (TArgA, TArgB)> f) {}
int main(int argc, char * argv[]) {
auto x = [] (int a, int b) { return a * b; };
Functor<int, int, int> (x);
return 0;
}
推荐答案
问题是编译器不知道您打算将 int,int
整合为 TArgs
的全部,因此尝试推论 TArgs
的其余部分来自参数 f
。
The issue is that the compiler doesn't know that you've intended int, int
to be the whole of TArgs
, and so tries to deduce the remainder of TArgs
from the argument f
.
例如,这将是有效的:
Functor<int, int, int>(std::function<int(int, int, char, float)>{});
// TArgs := {int, int, [...] char, float}
因此,您需要指示编译器不要尝试推断出 TArgs
的其余部分。例如,您可以这样写:
So you need to instruct the compiler to not try to deduce the remainder of TArgs
. For example, you could write:
(*Functor<int, int, int>)(x);
或者您可以将 Functor
与非分解的签名 Sig
:
Or you could write Functor
with a non-decomposed signature Sig
:
template <Sig>
void Functor(std::function<Sig> f) {}
或者您可以在非推论上下文中将 TArgs
的使用包装在参数 f
中:
Or you could wrap the use of TArgs
in the parameter f
in a non-deduced context:
template <typename TReturn, typename ... TArgs>
void Functor(std::function<std::conditional_t<false, void, TReturn (TArgs...)>> f) {}
这篇关于使用参数包将lambda转换为std :: function的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!