简体   繁体   English

从作为模板函数参数传递的std :: function推断返回值和参数类型?

[英]Deducing return and parameter type from std::function passed as a template function argument?

I've been looking around SO for a while now but cannot find quite the answer that I am looking for - this question is probably the closest to what I am thinking. 我一直在四处寻找SO,但是找不到我一直在寻找的答案- 这个问题可能最接近我的想法。

In a sentence: is it possible to declare a template function that takes a parameter of an std::function and deduce template parameters for both the return type and the parameter types of the function? 一句话:是否可以声明一个采用std::function参数的模板函数,并为该std::function的返回类型和参数类型推导出模板参数? Example: 例:

//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();
}

Is this because the function signature or function type is considered one thing in itself, and as such cannot be "broken" up? 这是因为函数签名或函数类型本身被视为一件事情,因此不能被“分解”吗? I realise there are decltype and std::result_of but cannot think how I might use them here. 我意识到这里有decltypestd::result_of但是无法思考我在这里如何使用它们。

As an additional point, how might I extend the second example to have multiple parameters and deduction, using variadic templates? 另外,如何使用可变参数模板将第二个示例扩展为具有多个参数和推导?

template<class R, class P>
void doSomethingElse(std::function<R(P)> f) {
    f(P{});
}

Will work, but it only works if you pass a std::function to the function and that function has one non void parameter. 可以,但是仅当您将std::function传递给该函数并且该函数具有一个非void参数时,该函数才有效。 This is kind of limiting though. 不过,这是一种限制。 You can use 您可以使用

template<class R, class... Args, class... Ts>
void doSomethingElse(std::function<R(Args...)> f, Ts&&... args) {
    f(std::forward<Args>(args)...);
}

Which will take any std::function and the arguments for it and calls them as if you did it in the call site. 它将接受任何std::function及其参数,并像在调用站点中一样调用它们。 This is still limiting though because the call site requires you use a std::function so you can't pass it anything implicitly convertible to a std::function . 但是这仍然是有限制的,因为调用站点要求您使用std::function所以您不能将任何隐式可转换为std::function传递给它。

With C++17 and class template argument deduction (CTAD) this is no longer an issue though. 使用C ++ 17和类模板参数推论 (CTAD)时,这不再是问题。 We can create an overload that takes any type, and then construct a std::function using CTAD to fill in the types for us. 我们可以创建任何类型的重载,然后使用CTAD构造一个std :: function来为我们填充类型。 That would look like 看起来像

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)...);
}

And now anything that isn't a std::function will go to void doSomethingElse(Func&& f, Args&&... args) , get converted to a std::function , and get passed to void doSomethingElse(std::function<R(Args...)> f, Args&&... args) so you can use the return type and argument(s) type(s) in there. 现在,所有不是std::function都将变为void doSomethingElse(Func&& f, Args&&... args) ,被转换为std::function ,并传递给void doSomethingElse(std::function<R(Args...)> f, Args&&... args)因此您可以在其中使用返回类型和参数类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM