为什么模板参数推导失败,std::函数回调的可变参数模板参数?
Why does template argument deduction failed with variadic template parameters of a std::function callback?
让我们考虑以下函数:
// run_cb_1(): Explicitly defined prototype
void run_cb_1(const std::function<void(int)> & callback, int p)
{
callback(p);
}
// run_cb_2(): One template parameter
template <typename T>
void run_cb_2(const std::function<void(T)> & callback, const T & t)
{
callback(t);
}
// run_cb_3(): Variable number of template parameters
template <typename ... Args>
void run_cb_3(const std::function<void(Args...)> & callback, const Args & ... args)
{
callback(args...);
}
现在,如果我想按如下方式使用这些函数:
int main()
{
auto f = [](int a){
std::cout << a << 'n';
};
run_cb_1(f, 5); // OK
run_cb_2(f, 5); // KO --> I understand why
run_cb_2<int>(f, 5); // OK
run_cb_3(f, 5); // KO --> I understand why
run_cb_3<int>(f, 5); // KO --> I don't understand why...
return 0;
}
我得到了一个带有run_cb_2()
和run_cb_3()
的"不匹配函数调用">,而它与run_cb_1()
一起工作得很好。
我认为它的行为符合预期,因为我没有提供模板参数的类型(因为它不能像run_cb_1()
那样简单地推断出来(。
但是指定模板类型可以解决run_cb_2()
的问题(正如我所期望的那样(,但不能解决run_cb_3()
的问题。
我知道我可以通过明确声明f
来解决它:
std::function<void(int)> f = [](int a){
std::cout << a << 'n';
};
或者通过将 f 传递为:
run_cb_2(std::function<void(int)>(f), 5);
run_cb_3(std::function<void(int)>(f), 5);
我的问题是:为什么即使显式指定模板类型,模板参数推断也会因run_cb_3()
(使用可变参数模板参数(而失败?
很明显,我错过了一些东西(也许是基本的(,但我不知道它是什么。
任何帮助将不胜感激。
失败的原因是编译器可以使用的类型不止一种。 当你这样做时
run_cb_2<int>(f, 5);
编译器查看run_cb_2
并看到只有一个模板参数。 既然您已经提供了它跳过扣除阶段并消除run_cb_2<int>
.
跟
run_cb_3<int>(f, 5);
你在另一条船上。run_cb_3
有一个可变参数模板参数,这意味着仅提供int
不足以跳过扣除。 您指定了第一个参数,但可能还有更多参数,因此它进入参数推断阶段以弄清楚它。 这意味着它会检查callback
,以确保它在那里推断的内容与它推断args
相匹配。 由于 lambda 不是std::function
因此无法从中推断出Args...
。 一旦发生这种情况,编译器就会停止并发出错误。
对于run_cb_3<int>
,你没有明确提供完整的Args...
,只有第一种类型;它可能有其他类型。
例如,它用于std::make_unique
等函数中:
template <class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args);
和
std::make_unique<MyObj>(var1, var2); // T = MyObj
// Args... = [decltype((var1)), decltype((var2))]
从论证中推导出额外的参数。
若要强制评估,可以使用:
(&run_cb_3<int>)(f, 5); // OK
演示
- 如何将成员函数作为回调参数传递给需要"typedef-ed"自由函数指针的函数?
- C++存储带有可变参数的回调
- C++ 事件管理器的回调,使用 std::function 和 std:bind 以及派生类作为参数
- 以特征类型作为参数的泛型函数回调
- C++模板函数中,指定回调函子/lambda 的参数类型,同时仍允许内联?
- 模板化回调参数的逆变,如 C# 中的逆变
- 带有参数的嵌入式系统上的最小c++回调
- 如何用不同的参数类型和数字回调函数
- 如何成功地将函数对象(或lambda)传递给trackbar回调的第二个参数(void*)
- v8 源代码中 ArrayMap 函数的回调 fn 参数是什么?
- 如何将提升回调作为参数传递给方法?
- 为什么模板参数推导失败,std::函数回调的可变参数模板参数?
- 回调参数中的协方差C++
- OpenGL 调试 错误回调函数的 ID 参数是什么?
- 如何使用 c++11 函数回调声明多个模板参数
- sqlite3 更改函数回调参数 void* not用于 int* C++
- 如何使用C++函数指针作为指向 C 函数指针/回调的参数
- 如何在 Lua 回调中检测可选的第一个参数
- 如何在 Windows 上将成员函数作为与蓝牙相关的参数回调函数传递
- C++可变参数回调