Clang模板匹配无法匹配基类继承的成员函数指针,哪个编译器合规?
问题:Clang与MSVC对成员函数指针模板参数推导的分歧
这段代码在MSVC中可正常编译,但在Clang中编译失败:
class Base { public: int bla() { return 1; } }; class Derived : public Base { }; template <typename T> void func(T (Derived::*method)()) { } int main() { func(&Derived::bla); }
Clang的报错信息如下:
<source>:19:3: error: 找不到匹配的'func'调用函数 19 | func(&Derived::bla); | ^~~~ <source>:13:6: note: 候选模板被忽略:无法将'Derived'与'Base'匹配 13 | void func(T (Derived::*method)()) | ^
根据C++标准,Clang的行为是正确的。
原因如下:
&Derived::bla的实际类型是int (Base::*)(),即指向基类Base的成员函数指针,而非int (Derived::*)()。虽然派生类对象可以调用基类成员函数,但成员函数指针的所属类类型是严格区分的。- 模板参数推导阶段,编译器需要将实参类型与形参模板
T (Derived::*)()匹配。由于Base和Derived是不同的类,模板参数T无法完成推导——这里不仅要匹配返回值类型T,还要匹配成员函数指针的所属类,而两者不兼容,因此推导失败,Clang的报错符合标准。 - MSVC的行为属于非标准扩展,它宽松地允许基类成员函数指针隐式转换为派生类成员函数指针并完成模板推导,但这并不符合C++标准的要求。
内容的提问来源于stack exchange,提问作者Andor Pathó
相关产品推荐
相关产品推荐

