使用默认模板参数推导模板函数指针的模板参数
Deduce template parameter for a template function pointer with default template parameter
虽然这个问题看起来有点混乱。代码很简单:
template <typename T>
void tfunc(T&& getter)
{
}
template <typename T = void>
void voidfunc()
{}
int main() {
tfunc(&voidfunc); // error: could not deduce template argument for 'T'
tfunc(&voidfunc<int>); // ok
voidfunc(); // calling using default template parameter is ok.
}
clang 11& msvc visual studio 2019 16.7 报错。
为什么我需要明确指定模板参数?
背景
- 该参数是一个虚拟参数,只是为了将
voidfunc
的实例化延迟到使用它的地方。类型并不重要。
&voidfunc
由 clangAST 生成的一些代码使用,否则如果它是模板,我需要调整生成器以编写 &voidfuc<>
。
__declspec(property(put=voidfunc))
这个 clang/msvc 扩展需要 voidfunc
而不是 voidfunc<>
如果给定的函数是模板,我已经将生成器调整为输出 &voidfunc<>
,如 @Jarod42 所说。目前有效。
如评论所述,这种情况直到C++20才在标准中明确,当时cleaned up是为了更好地支持约束函数的新特性。新规范在以前的语言版本中有意义(忽略约束的可能性),因此希望实现最终将在所有地方支持这种用法。
默认模板参数的模板参数不参与模板类型推导。
这就是为什么您必须显式提供 voidfunc 的模板参数。
顺便说一句,Nicolai Josuttis 在他 2017 年的 cppcon 演讲中解释了这一点,主题是“琐碎的移动语义的噩梦 类:
https://www.youtube.com/watch?v=PNRju6_yn3o&list=RDCMUCMlGfpWw-RUdWX_JbLCukXg&index=2
虽然这个问题看起来有点混乱。代码很简单:
template <typename T>
void tfunc(T&& getter)
{
}
template <typename T = void>
void voidfunc()
{}
int main() {
tfunc(&voidfunc); // error: could not deduce template argument for 'T'
tfunc(&voidfunc<int>); // ok
voidfunc(); // calling using default template parameter is ok.
}
clang 11& msvc visual studio 2019 16.7 报错。 为什么我需要明确指定模板参数?
背景
- 该参数是一个虚拟参数,只是为了将
voidfunc
的实例化延迟到使用它的地方。类型并不重要。 &voidfunc
由 clangAST 生成的一些代码使用,否则如果它是模板,我需要调整生成器以编写&voidfuc<>
。__declspec(property(put=voidfunc))
这个 clang/msvc 扩展需要voidfunc
而不是voidfunc<>
如果给定的函数是模板,我已经将生成器调整为输出 &voidfunc<>
,如 @Jarod42 所说。目前有效。
如评论所述,这种情况直到C++20才在标准中明确,当时cleaned up是为了更好地支持约束函数的新特性。新规范在以前的语言版本中有意义(忽略约束的可能性),因此希望实现最终将在所有地方支持这种用法。
默认模板参数的模板参数不参与模板类型推导。 这就是为什么您必须显式提供 voidfunc 的模板参数。
顺便说一句,Nicolai Josuttis 在他 2017 年的 cppcon 演讲中解释了这一点,主题是“琐碎的移动语义的噩梦 类:
https://www.youtube.com/watch?v=PNRju6_yn3o&list=RDCMUCMlGfpWw-RUdWX_JbLCukXg&index=2