c++ - 数组到指针的转换 + rvalue-ref : Overload resolution difference GCC vs clang

标签 c++ language-lawyer implicit-conversion overload-resolution

#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/

相关文章:

c# - 从 C# 代码调用 C++ native dll

java - ArrayList 与 Vector 通过引用传递

c++ - 在早期检测成语实现中使用 void 模板参数

java - Java泛型和集合中的混淆句

asp.net-mvc - 使用隐式/显式转换运算符是否违反单一职责模式而支持 DRY?

c++ - 缩小转换范围

c++ - 如何使用 SFINAE 选择最接近的匹配类型特征?

C 最低标准要求

c++ - 类转换(有点复制)构造函数到类的指针

c++ - 字符数组输出不正确