这种重载分辨率是否正确?

Bri*_*ian 11 c++ language-lawyer overload-resolution c++11

From:重载char*和std :: string是否安全?

#include <string>
#include <iostream>
void foo(std::string str) {
  std::cout << "std::string\n";
}

void foo(char* str) {
  std::cout << "char*\n";
}

int main(int argc, char *argv[]) {
  foo("Hello");
}
Run Code Online (Sandbox Code Playgroud)

上面的代码在编译时打印"char*" g++-4.9.0 -ansi -pedantic -std=c++11.

我觉得这是不正确的,因为字符串文字的类型是" n的 数组const char",并且不应该const char*用它初始化非,因此std::string应该选择重载.gcc是否违反了标准?

Ded*_*tor 7

首先,字符串文字的类型:它们都是字符类型的常量数组.

2.14.5字符串文字[lex.string]

7以u8开头的字符串文字,例如u8"asdf",是一个UTF-8字符串文字,并使用UTF-8编码的给定字符进行初始化.
8普通字符串文字和UTF-8字符串文字也称为窄字符串文字.窄字符串文字的类型为"n const char数组",其中n是下面定义的字符串大小,并且具有静态存储持续时间(3.7).
9以u开头的字符串文字,例如u"asdf",是一个char16_t字符串文字.char16_t字符串文字的类型为"n const char16_t的数组",其中n是下面定义的字符串的大小; 它具有静态存储持续时间,并使用给定的字符进行初始化.单个c-char可以以代理对的形式产生多个char16_t字符.
10以U开头的字符串文字,例如U"asdf",是一个char32_t字符串文字.char32_t字符串文字的类型为"n const char32_t的数组",其中n是下面定义的字符串的大小; 它具有静态存储持续时间,并使用给定的字符进行初始化.
11以L开头的字符串文字,例如L"asdf",是一个宽字符串文字.宽字符串文字的类型为"n const wchar_t的数组",其中n是字符串的大小,如下所示; 它具有静态存储持续时间,并使用给定的字符进行初始化.

接下来,让我们看看我们只有标准数组衰减,所以从:T[#]到T*:

4.2数组到指针的转换[conv.array]

1可以将"数组NT"或"未知T的数组"类型的左值或右值转换为"指向T的指针"的prvalue.结果是指向数组的第一个元素的指针.

最后,让我们看看任何符合标准的扩展都不能改变正确程序的含义:

1.4实施合规[intro.compliance]

1可诊断规则集包含本国际标准中的所有句法和语义规则,但那些包含"无需诊断"的明确表示法或描述为"未定义行为"的规则除外
.2虽然本国际标准规定只有C++实现的要求,如果这些要求被表达为对程序,程序的一部分或程序的执行的要求,那么这些要求通常更容易理解.这些要求具有以下含义:

  • 如果某个程序不违反本国际标准中的规则,则符合条件的实施应在其资源限制内接受并正确执行该程序.
  • 如果程序包含违反任何可诊断规则或本标准中描述的构造的发生,如果实现不支持该构造,则符合条件的实现应发出至少一条诊断消息.
  • 如果程序包含违反不需要诊断的规则,则本国际标准不要求对该程序的实施.

总而言之,这是一个编译器错误.

(在C++ 11(C++ 03)之前,转换是允许的但是已弃用,所以它本来是正确的.如果发生这种情况的诊断不是必需的,而是作为实施质量问题提供的.)

这是一个GCC错误,也是一个clang bug.
clang的错误报告:http://llvm.org/bugs/show_bug.cgi? id = 16314(感谢TC发现错误报告.)

来自clang bug-report的测试用例,它更短:

void f(char*);
int &f(...);
int &r = f("foo");
Run Code Online (Sandbox Code Playgroud)