c++ - 将函数传递给可变参数函数模板
问题描述
考虑以下函数模板:
template<typename RetType, typename... ArgTypes>
void foo0(std::function<RetType(ArgTypes...)> f) {}
template<typename RetType, typename ArgType>
void foo1(std::function<RetType(ArgType)> f) {}
以及以下功能:
void bar(int n) {}
为什么会出现以下情况:
foo0<void, int>(bar); // does not compile
foo1<void, int>(bar); // compiles fine
编译错误是(gcc-8 with C++17):
error: no matching function for call to 'foo0<void, int>(void (&)(int))'
foo0<void, int>(bar);
^
note: candidate: 'template<class RetType, class ... ArgTypes> void foo0(std::function<_Res(_ArgTypes ...)>)'
void foo0(std::function<RetType(ArgTypes...)> f) {}
^~~~
note: template argument deduction/substitution failed:
note: mismatched types 'std::function<void(_ArgTypes ...)>' and 'void (*)(int)'
foo0<void, int>(bar);
使用虚拟模板
template<typename T>
void bar(int n) {}
在 gcc-8 中可以foo0<void, int>(bar<int>);
正常编译,但在 Apple LLVM 版本 10.0.0 (clang-1000.11.45.5) 中使用 clang 会出错。
铿锵的错误是
error: no matching function for call to 'foo0'
foo0<void, int>(bar<int>);
^~~~~~~~~~~~~~~
note: candidate template ignored: could not match 'function<void (int, type-parameter-0-1...)>' against 'void (*)(int)'
void foo0(std::function<RetType(ArgTypes...)> f) {}
解决方案
为什么会出现以下情况 [?]
当你打电话时算一算
foo0<void, int>(bar); // compilation error
foo1<void, int>(bar); // compile
foo0()
andfoo1()
期望 a std::function
andbar
是指向可以转换为 astd::function
但不是 a的函数的指针std::function
。
在这种foo1()
情况下,您显式了 bothRetType
和ArgType
模板参数,因此编译器可以转换bar
为 astd::function<void(int)>
并且一切顺利。
但foo0()
情况有所不同,因为模板参数ArgTypes...
是一个可变参数,并且调用foo0<void, int>(bar)
您并没有显式显示完整的ArgTypes...
可变参数列表,而只是第一种类型。
如果我没记错的话,问题是编译器试图ArgTypes...
从bar
参数中推断出其余部分,但bar
不是,std::function
所以编译器无法推断出其余部分ArgTypes...
,所以错误。
我想
foo0<void, int>(std::function<void(int)>{bar});
或者干脆
foo0(std::function<void(int)>{bar});
或(仅限 C++17)也
foo0(std::function{bar});
应该编译因为,foo0()
这样调用,函数接收到一个std::function
,所以编译器可以完全推导出模板参数。
我不明白bar()
带有虚拟模板参数的版本如何
foo0<void, int>(bar<int>);
可以用 g++-8 编译,我想这是一个 g++ 错误。
推荐阅读
- react-native - 有没有办法在加载后一次在 React-Native 中重新加载屏幕?
- java - 发送 1 个 JSON 和 1 个多表单/数据的 Swagger-UI 问题
- javascript - 如何用电子跨平台录制音视频
- mysql - 在 eloquent 模型中查询
- boto3 - 使用 python SDK 从 S3 下载文件
- active-directory - Liferay 6.2 GA6 - 无法访问 LDAP“userPassword”属性
- c - 为什么 Ctrl+C 在我的终端中不起作用?
- javascript - 没有框架的 NodeJS:findById
- c# - 在 Unity 中,为什么我可以通过按下按钮将相机切换到 WorldView,但在使用人脸管理器的同时无法在开始或更新循环中执行此操作?
- python - 如何在 python Django 中发送连续响应?