使用被 clang 拒绝但被 gcc 和 msvc 接受的引用类型调用时函数模板重载

问题描述 投票:0回答:1

我编写了以下具有重载函数模板的程序,但该程序被 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:nope, gcc:ok, msvc:ok
} 

叮 说:

<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++ 标准,哪个编译器是正确的。

c++ language-lawyer
1个回答
0
投票

首先,重载决策中存在潜在的歧义,因为

const T&&
,当替换
int&
时,结果是
int&
,而不是
const int&

因此,就参数的隐式转换序列而言,两种重载同样可行。

现在的问题是,根据函数模板的部分排序规则,其中一个模板是否比另一个模板“更专业”。 在此部分排序中,函数参数上的引用和顶级 cv 限定符首先被忽略,从而使两个模板完全等效。

但是,如果两个模板的相应参数都是引用,并且其中一个比另一个更符合 cv 资格,那么如果转换后的参数在其他方面相同(如此处),则存在一个有利于更符合 cv 资格的决胜局参数,无论引用是左值引用还是右值引用。请参阅

[temp.deduct.partial]/9.2

所以 Clang 是不正确的。第二个函数模板比第一个函数模板更专业,因此在重载决策中应优先使用。

© www.soinside.com 2019 - 2024. All rights reserved.