来自:Is it safe to overload char* and 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");
}
以上代码打印&#34; char *&#34;使用g++-4.9.0 -ansi -pedantic -std=c++11
编译时。
我觉得这是不正确的,因为字符串文字的类型是&#34; n const char
&#34;的数组,它不应该是可以用它来初始化非const
char*
,因此应该选择std::string
重载。 gcc是否违反了标准?
答案 0 :(得分:7)
首先,字符串文字的类型:它们都是字符类型的常量数组。
2.14.5字符串文字[lex.string]
7以u8开头的字符串文字,例如u8&#34; asdf&#34;,是一个UTF-8字符串文字,并使用UTF-8编码的给定字符进行初始化。
8普通字符串文字和UTF-8字符串文字也称为窄字符串文字。窄字符串文字的类型为“n const char数组”,其中n是下面定义的字符串大小,并且具有静态存储持续时间(3.7)。
9以u开头的字符串文字,例如u&#34; asdf&#34;,是一个char16_t字符串文字。 char16_t字符串文字的类型为“n const char16_t的数组”,其中n是下面定义的字符串的大小;它具有静态存储持续时间,并使用给定的字符进行初始化。单个c-char可以以代理对的形式产生多个char16_t字符 10以U开头的字符串文字,例如U&#34; asdf&#34;,是一个char32_t字符串文字。 char32_t字符串文字的类型为“n const char32_t的数组”,其中n是下面定义的字符串的大小;它具有静态存储持续时间,并使用给定的字符进行初始化 11以L开头的字符串文字,例如L&#34; asdf&#34;,是一个宽字符串文字。宽字符串文字的类型为“n const wchar_t的数组”,其中n是字符串的大小,如下所示;它具有静态存储持续时间,并使用给定的字符进行初始化。
接下来,我们看到我们只有标准数组衰减,因此从T[#]
到T*
:
4.2数组到指针的转换[conv.array]
1类型为“N T数组”或“未知T的数组”的左值或右值可以转换为“指向T的指针”类型的prvalue。结果是指向数组的第一个元素的指针。
最后,让我们看看任何符合标准的扩展都不能改变正确程序的含义:
1.4实施合规性[intro.compliance]
1可诊断规则集包含本国际标准中的所有语法和语义规则,但那些包含“无需诊断”的明确表示法或描述为“未定义行为”的规则除外。
2虽然本国际标准仅规定了对C ++实现的要求,但如果将这些要求表达为对程序,程序部分或程序执行的要求,则这些要求通常更容易理解。这些要求具有以下含义:
- 如果某个程序不违反本国际标准中的规则,则符合条件的实施应在其资源限制内接受并正确执行该程序。
- 如果程序包含违反任何可诊断规则或本标准中描述的构造的发生,如果实现不支持该构造,则符合条件的实现应发出至少一条诊断消息。 / LI>
- 如果某个程序违反了不需要诊断的规则,则为国际 标准对该程序的实施没有要求。
因此,总而言之,它是一个编译器错误。
(在C ++ 11(C ++ 03)之前,转换是允许的但是已弃用,所以它本来是正确的。如果发生这种情况的诊断不是必需的,而是作为实施质量问题提供的。)
这是一个海湾合作委员会的错误,也是一个铿锵的错误 clang的错误报告:http://llvm.org/bugs/show_bug.cgi?id=16314(Thanks to T.C. for finding the bug report.)
来自clang bug-report的测试用例,它更短:
void f(char*);
int &f(...);
int &r = f("foo");