C++中函数类型参数场景下的类模板实参推导问题
模板构造函数的实参自动推导问题解析
先来看这段引发编译器差异的代码:
template<typename T> struct A{ A(T f()){ f(); } }; int foo() { return 1; } int main() { [[maybe_unused]] A<int> x = foo; // 所有编译器均能通过 [[maybe_unused]] A y = foo; // Clang报错 }
现象说明
这段代码里,模板结构体A的构造函数接收一个T()类型的函数参数。我们尝试了两种对象构造方式:
- 显式指定模板参数的
A<int> x = foo:所有编译器都能正常编译; - 依赖模板实参自动推导的
A y = foo:GCC可以顺利编译,但Clang会抛出错误。
Clang的报错信息如下:
error: no viable constructor or deduction guide for deduction of template arguments of 'A'
note: candidate template ignored: could not match 'A' against 'int ()()'
note: candidate template ignored: could not match 'T ()' against 'int ()()'
问题分析
首先可以明确:这段代码并不是格式不良的代码,问题出在Clang的实现缺失了对应的推导支持。
根据C++标准的规则,当我们传入函数名foo时,它会隐式退化为函数指针int (*)()。对于A的构造函数参数T(),模板推导应当能够通过函数指针到函数类型的适配逻辑,推导出T=int。GCC的行为是符合标准要求的,而Clang在这里的推导逻辑没有处理这种函数类型与函数指针的隐式转换场景,导致无法完成模板参数的推导。
如果想让Clang也能编译通过,我们可以显式添加一个推导指南来辅助它:
template<typename T> A(T (*)()) -> A<T>;
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

