调用引用类型的函数模板重载:Clang拒接GCC/MSVC接受,谁符合C++标准?
函数模板重载的编译器分歧:哪个符合C++标准?
我编写了一个包含重载函数模板的程序,Clang编译报错,但GCC和MSVC能正常编译运行。
#include <utility> #include <iostream> template< class T > void f( T& t ){} ; template< class T > void f( const T&& ) {}; int main() { int i = 0; f<int&>(i); // Clang: 编译报错,GCC/MSVC: 正常通过 }
Clang的报错信息如下:
<source>:10:5: error: call to 'f' is ambiguous 10 | f<int&>(i); //clang:nope, gcc:ok, msvc:ok | ^~~~~~~ <source>:4:26: note: candidate function [with T = int &] 4 | template< class T > void f( T& t ){} ; | ^ <source>:5:26: note: candidate function [with T = int &] 5 | template< class T > void f( const T&& ) {}; |
根据C标准,Clang的处理是正确的,原因如下:
当显式指定模板参数T=int&时,结合C的引用折叠规则与引用类型的cv限定规则,两个模板会被实例化为完全相同的函数签名:
- 第一个模板
void f(T&):T&展开为int& &,根据引用折叠规则,左值引用叠加后仍为左值引用,最终签名为void f(int&)。 - 第二个模板
void f(const T&&):C++标准规定引用类型不能被const/volatile限定,因此const T(其中T=int&)等价于int&;再结合引用折叠规则,int& &&会折叠为int&,最终签名同样是void f(int&)。
两个实例化后的函数完全一致,调用时必然存在歧义,Clang的报错完全符合标准。GCC和MSVC的编译通过属于非标准的宽松处理,不符合规范要求。
内容的提问来源于stack exchange,提问作者Anoop Rana
相关产品推荐
相关产品推荐

