#include <iostream>
#define FUNC() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
void foo(char const*&& ) FUNC() // A
void foo(char const(&)[4]) FUNC() // B
int main()
{
foo("bar");
}
Demo当在第一个重载 (A) 的参数类型中使用右值引用时,clang current master 明确地选择重载 A 而不是 B。另一方面,GCC current master 提示歧义。
我很惊讶字符串文字的左值是 4
char const
( [expr.prim.literal]/1 , [lex.string]/6 ) 应该更喜欢重载 A 上的数组到指针转换,而不是重载 B 上的恒等转换。没有右值引用,即
void foo(char const*)
,GCC 和 clang 都拒绝调用不明确。这也是我不完全理解的事情,因为我会猜测仍然存在数组到指针的转换,因此 [over.ics.rank]p3.2.1适用:
Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if
- (3.2.1) S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by [over.ics.scs], excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence) or, if not that,
在这两种情况下发生了什么?
最佳答案
(这只是部分答案,涵盖了第二种情况)
What is going on in either case?
关于第二种情况,至于为什么以下重载
void foo(char const* ) FUNC() // A
void foo(char const(&)[4]) FUNC() // B
产生不明确的重载(对于 Clang 和 GCC); [over.ics.rank]/3.2.1似乎比 A 更喜欢 B,它是一个恒等转换,需要一个数组到指针的转换,而后者又属于左值转换的转换类别:Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if
- (3.2.1) S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by [over.ics.scs], excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence) or, if not that,
- [...]
然而,正如我所解释的首先强调上面的段,Lvalue Transformation:s 在应用 [over.ics.rank]/3.2.1 时从序列 S1 和 S2 中排除,并且第二个强调的段仅在应用此排除后才适用。
正如所指出的in a comment by @LanguageLawyer ,规则确实允许这种歧义在 CWG 1789 中突出显示。事实上,自 2013 年以来没有任何进展或反馈。
1789. Array reference vs array decay in overload resolution
- Section: 12.4.4.3 [over.ics.rank]
- Status: drafting
- Submitter: Faisal Vali
- Date: 2013-10-01
The current rules make an example like
template<class T, size_t N> void foo(T (&)[N]); template<class T> void foo(T *t); int arr[3]{1, 2, 3}; foo(arr);
ambiguous, even though the first is an identity match and the second requires an lvalue transformation. Is this desirable?
关于c++ - 数组到指针的转换 + rvalue-ref : Overload resolution difference GCC vs clang,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65705233/