【问题标题】:Array-to-pointer conversion + rvalue-ref: Overload resolution difference GCC vs clang数组到指针的转换 + rvalue-ref:重载分辨率差异 GCC vs clang
【发布时间】:2021-04-18 15:51:36
【问题描述】:
#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 当前主机明确地选择重载 A 而不是 B。另一方面,GCC 当前主机抱怨有歧义。

我很惊讶字符串文字是 4 char const 的左值([expr.prim.literal]/1[lex.string]/6)应该更喜欢重载 A 上的数组到指针转换重载 B 上的恒等式转换。

如果没有右值引用,即void foo(char const*),GCC 和 clang 都会因为不明确而拒绝调用。这也是我不完全理解的事情,因为我猜到仍然存在数组到指针的转换,因此 [over.ics.rank]p3.2.1 适用:

  • 标准转换序列S1是比标准转换序列S2更好的转换序列如果

    • (3.2.1) S1 是 S2 的适当子序列(比较 [over.ics.scs] 定义的规范形式的转换序列,不包括 任何左值变换;身份转换序列是 被认为是任何非身份转换的子序列 序列),或者,如果不是,

这两种情况发生了什么?

【问题讨论】:

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


【解决方案1】:

(这只是部分答案,涵盖了第二种情况)

这两种情况发生了什么?

关于第二种情况,至于为什么会出现下面的重载

void foo(char const*     ) FUNC() // A
void foo(char const(&)[4]) FUNC() // B

产生模棱两可的重载(对于 Clang 和 GCC); [over.ics.rank]/3.2.1 似乎更喜欢 B,它是一个身份转换,而不是 A,需要 数组到指针的转换,而后者又属于 转换类别 >左值变换

标准转换序列S1是比标准转换序列S2更好的转换序列如果

  • (3.2.1) S1 是 S2 的适当子序列(比较 [over.ics.scs] 定义的规范形式的转换序列,不包括任何左值变换身份转换序列被认为是任何非身份转换序列的子序列)或者,如果不是,
  • [...]

但是,正如我解释上面的首先强调部分,在应用 [over.ics.rank]/3.2.1 时,左值变换:s 被排除在序列 S1 和 S2 之外,而 第二个强调段仅​​在应用此排除后才适用。


正如in a comment by @LanguageLawyer 所指出的,规则确实允许这种歧义在CWG 1789 中得到强调,因为自 2013 年以来没有看到任何进展或反馈。

1789。重载分辨率中的数组引用与数组衰减

  • 部分:12.4.4.3 [over.ics.rank]
  • 状态:起草
  • 提交者:Faisal Vali
  • 日期:2013-10-01

目前的规则举个例子

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);

模棱两可,即使第一个是身份匹配,而第二个 需要左值转换。这是可取的吗?

【讨论】:

  • 尽管“排除”指的是什么,但我并不是 100% 清楚。是指对子序列的检测(=我们只看序列中没有左值变换的部分来判断它是否是子序列)还是指排除这3.2.1点?跨度>
  • 虽然我不确定这是否重要:如果我们忽略左值转换,那么恒等转换就不是数组到指针转换的正确子序列——它是相同的转换顺序。
  • @dyp 我同意 3.2.1 关于排除的措辞有些不清楚。不过,我无法解释为什么 Clang 会选择第一个示例的右值重载。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多