dyp*_*dyp 7 c++ language-lawyer overload-resolution implicit-conversion
#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");
}
Run Code Online (Sandbox Code Playgroud)
当在第一个重载 (A) 的参数类型中使用右值引用时,clang current master 明确地选择重载 A 而不是 B。另一方面,GCC current master 抱怨歧义。
我很惊讶字符串文字是4char 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]定义的规范形式的转换序列,不包括任何左值转换;恒等转换序列被认为是任何非-身份转换序列),或者,如果不是,
在这两种情况下发生了什么?
(这只是部分答案,涵盖第二种情况)
这两种情况是怎么回事?
关于第二种情况,至于为什么会出现下面的重载
void foo(char const* ) FUNC() // A
void foo(char const(&)[4]) FUNC() // B
Run Code Online (Sandbox Code Playgroud)
产生不明确的重载(对于 Clang 和 GCC);[over.ics.rank]/3.2.1似乎比 A 更倾向于 B,它是恒等转换,需要数组到指针的转换,而这又属于Lvalue Transformation的转换类别:
标准转换序列 S1 是比标准转换序列 S2 更好的转换序列,如果
- (3.2.1) S1 是 S2 的真子序列(比较 [over.ics.scs] 定义的规范形式的转换序列,不包括任何左值变换;恒等转换序列被认为是任何非身份转换序列) 或者,如果不是这样,
- [...]
然而,正如我解释上面第一个强调的段一样,在应用 [over.ics.rank]/3.2.1 时,左值变换:s 被从序列 S1 和 S2 中排除,而第二个强调的段仅在应用此排除后才适用。
正如@LanguageLawyer 在评论中指出的那样, CWG 1789中强调了规则确实允许这种模糊性,但自 2013 年以来,该规则尚未取得任何进展或反馈。
1789.重载解析中的数组引用与数组衰减
- 节:12.4.4.3 [over.ics.rank]
- 状态:起草中
- 提交者:费萨尔·瓦利
- 日期:2013年10月1日
当前的规则举了一个例子
Run Code Online (Sandbox Code Playgroud)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);
不明确,即使第一个是身份匹配,第二个需要左值转换。这是可取的吗?