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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从std :: function中推导返回和参数类型作为模板函数参数传递?相关的知识,希望对你有一定的参考价值。

我一直在寻找一段时间,但找不到我想要的答案 - this question可能是我最接近我的想法。

在一个句子中:是否可以声明一个模板函数,它接受std::function的参数并推导函数的返回类型和参数类型的模板参数?例:

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

这是因为函数签名或函数类型本身被认为是一件事,因此不能被“打破”吗?我意识到有decltypestd::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),这样你就可以在那里使用返回类型和参数类型。

以上是关于从std :: function中推导返回和参数类型作为模板函数参数传递?的主要内容,如果未能解决你的问题,请参考以下文章

std::function 作为模板参数

模板函数替换仅在一个参数中未使用std :: function时才起作用

C++ std::function怎么用

类数据成员中可以使用模板参数推导吗?

如何返回使用参数包定义的成员函数的 std::function 对象?

推导返回类型模板 C++