c++ - 这个重载决议是否正确?

标签 c++ c++11 language-lawyer overload-resolution

发件人: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");
}

以上代码在使用 g++-4.9.0 -ansi -pedantic -std=c++11 编译时打印“char*”。

我觉得这是不正确的,因为字符串字面量的类型是“array of n const char”,应该不可能初始化一个非 const char* ,因此应该选择 std::string 重载。 gcc 是否违反了这里的标准?

最佳答案

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

2.14.5 String literals [lex.string]

7 A string literal that begins with u8, such as u8"asdf", is a UTF-8 string literal and is initialized with the given characters as encoded in UTF-8.
8 Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration (3.7).
9 A string literal that begins with u, such as u"asdf", is a char16_t string literal. A char16_t string literal has type “array of n const char16_t”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters. A single c-char may produce more than one char16_t character in the form of surrogate pairs.
10 A string literal that begins with U, such as U"asdf", is a char32_t string literal. A char32_t string literal has type “array of n const char32_t”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters.
11 A string literal that begins with L, such as L"asdf", is a wide string literal. A wide string literal has type “array of n const wchar_t”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters.

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

4.2 Array-to-pointer conversion [conv.array]

1 An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.

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

1.4 Implementation compliance [intro.compliance]

1 The set of diagnosable rules consists of all syntactic and semantic rules in this International Standard except for those rules containing an explicit notation that “no diagnostic is required” or which are described as resulting in “undefined behavior.”
2 Although this International Standard states only requirements on C++ implementations, those requirements are often easier to understand if they are phrased as requirements on programs, parts of programs, or execution of programs. Such requirements have the following meaning:

  • If a program contains no violations of the rules in this International Standard, a conforming implementation shall, within its resource limits, accept and correctly execute2 that program.
  • If a program contains a violation of any diagnosable rule or an occurrence of a construct described in this Standard as “conditionally-supported” when the implementation does not support that construct, a conforming implementation shall issue at least one diagnostic message.
  • If a program contains a violation of a rule for which no diagnostic is required, this International Standard places no requirement on implementations with respect to that program.

因此,总而言之,这是一个编译器错误。

(在 C++11 (C++03) 之前,允许转换但已弃用,因此它应该是正确的。如果它发生,则不需要诊断,但作为实现质量问题提供。)

这是一个 GCC 错误(尚未找到错误报告),也是一个 clang bug (found by T.C.)。

来自 clang 错误报告的测试用例,它更短:

void f(char*);
int &f(...);
int &r = f("foo");

关于c++ - 这个重载决议是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24662385/

相关文章:

c++ - 生成文件 : converting file extension

c++ - C++ 中的 string[length()] 可以吗?

c++ - 通过 unsigned char[] 创建隐式对象 - reinterpret_cast 为隐式对象是否合法? (P0593)

c++ - C++中的声明和定义

c++ - 在 C++20 中使用 `std::bit_cast` 创建闭包 (lambda) 对象是否有效?

c++ - 非重复系列的非重复数字

c++ - 读取多个(所有)未决数据报

c++ - 析构函数在 C++ 中是如何工作的

c++ - const 引用的默认参数中使用的统一初始值设定项

c++ - 强制类的 const 成员在编译时进行评估