考虑这个简单的(坏的)函数模板,这个网站上有很多变体:
template <typename R, typename... Args>
R call_with(std::function<R(Args...)> f,
Args... args)
{
return f(args...);
}
还有两次调用它的尝试:
call_with([]{}); // (a)
call_with<void>([]{}); // (b)
我不能调用 (a)
因为 lambda 不是 std::function<R(Args...)>
所以模板推导失败。直截了当。
然而,(b)
也失败了。我怀疑这是因为编译器无法确定我的意思是提供所有类型参数以及我只是提供的原因 R
- 所以它试图(但失败了)推断出 Args...
出于与初始调用失败相同的原因。
有没有办法明确指定我提供所有模板参数?澄清一下,我仅对如何显式提供模板参数以便不进行模板推导感兴趣——我不是在寻找正确的写法 call_with
或者在使用 lambda 调用时使模板推导成功的方法。
最佳答案
对您编辑过的问题的简短回答是:如果您不能更改call_with()
的声明,则要么使用@CoffeeandCode 演示的类型转换,要么使用描述的技术下面为 call_with()
创建一个包装器。
问题在于编译器试图从第一个函数参数中推导出模板参数。如果您编写类似 this 的代码,则可以防止这种情况发生。 :
#include <functional>
#include <iostream>
// identity is a useful meta-function to have around.
// There is no std::identity, alas.
template< typename T>
struct identity
{
using type = T;
};
template <typename R, typename... Args>
R call_with( typename identity<std::function<R(Args...)>>::type f,
Args... args)
{
return f(args...);
}
int main()
{
call_with<void>([](int){ std::cout << "called" << std::endl; }, 2);
}
使用模板元函数“生成”std::function 类型意味着编译器甚至不能尝试从第一个参数推断出函数类型,它只会使用其他参数。
当然,您仍然需要显式提供返回类型,但对于其他参数,您现在可以选择是显式指定它们还是让编译器根据给定的参数推导出它们。
如果你真的想强制提供而不是推导所有模板参数,你也可以通过这种方式将参数包包装在 identity
的调用中:
template <typename R, typename... Args>
R call_with( typename identity<std::function<R(Args...)>>::type f,
typename identity<Args>::type... args)
总而言之,如果你想阻止编译器推导出也作为函数参数出现的函数模板参数类型,请将它们包装在元函数中,例如 identity
。
关于c++ - 使用空参数包显式调用可变函数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31440593/