使用参数包将lambda转换为std :: function [英] Cast lambda to std::function with parameter pack

查看:89
本文介绍了使用参数包将lambda转换为std :: function的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于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::functions, 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆