GCC与Clang均拒绝重载集地址的函数调用是否符合C++标准?
结论
GCC和Clang的实现完全符合C++标准,你对标准条款的适用场景存在理解偏差。
核心差异分析
你给出的示例代码如下:
struct A{ static void fun(int){} void fun(double){} void show(){ (&A::fun)(0); //#1 不合法 //A::fun(0); //#2 合法 } }; int main() { A::fun(0); }
1. 两种写法的本质区别
#2的A::fun(0):后缀表达式A::fun是合法的重载集,可直接参与函数调用的重载决议,传入参数0会精准匹配静态成员void fun(int),因此编译合法。#1的(&A::fun)(0):第一步需要先对&A::fun求值,而根据[over.over]条款的要求,取重载集地址的表达式必须存在明确的目标类型才能确定具体选取哪个函数,函数调用的上下文并不会为&A::fun提供目标类型推导的依据,因此该表达式在求值阶段就已经不合法,不会进入后续调用参数匹配的环节。
2. 对标准条款的误解说明
你引用的[over.match.call#general-2]条款,适用前提是后缀表达式已经是一个确定类型的函数指针/地址,而你遇到的报错发生在更早的&A::fun求值阶段,和该条款无关。
你可以通过显式指定目标类型验证这一点:
// 显式指定取static void fun(int)的地址,可正常编译运行 (static_cast<void(*)(int)>(&A::fun))(0);
以上写法会先通过显式类型转换为&A::fun提供明确的目标类型,选出静态成员函数的地址,再执行调用,完全符合标准要求。
内容的提问来源于stack exchange,提问作者xmh0511
相关产品推荐
相关产品推荐

