C++20中无前置声明的函数模板友元声明合法性及编译器行为正确性咨询
C++20中无前置声明的函数模板友元声明合法性及编译器行为正确性咨询
咱们先把问题拆解清楚,先看你给出的这段代码:
template <typename T> class A { friend void f<>(A&); int i = 0; }; template <typename T> void f(A<T>& a) { a.i = 1; }
首先说C17及更早的情况:这段代码确实不合法,所有编译器拒绝它是完全符合当时标准的。原因很直接——你在类模板A里写的friend void f<>(A&);,本质是在声明「函数模板f的一个特化」作为友元,但此时f的主模板还根本没被声明过。在C17的规则里,你不能随便引用一个连影子都没有的模板的特化,所以编译器报错是理所应当的。
到了C++20,标准做了针对性的规则改进,允许在类模板中声明函数模板的特化作为友元,哪怕这个函数模板的主模板还没前置声明,只要后续代码里出现了能匹配这个特化的主模板定义,编译器就可以把之前的友元声明和后面的主模板绑定起来。
所以GCC和MSVC在C20模式下接受这段代码,是正确实现了C20的新规则;而Clang还在报错,大概率是对这个C++20特性的支持还没跟上,属于编译器实现的滞后问题,而非标准本身的要求。
简单总结:
- C++17及更早:代码不合法,所有编译器拒绝是正确行为
- C++20:代码合法,GCC、MSVC的处理符合标准;Clang的报错是未完全支持该特性的表现
内容来源于stack exchange
相关产品推荐
相关产品推荐

