为什么 std::string 构造函数不能只接受一个字符?

lin*_*109 5 c++ string constructor type-conversion char

在使用函数模板时,我正在研究如何char在 C++ 中将 a 转换为长度为 1 的字符串,我发现使用 fill 构造函数std::string(1, c)将 a 转换char为字符串,遵循“重复char c1 次形成字符串”的逻辑。但是,没有定义std::string只接受 achar并将其转换为 a的构造函数重载std::string

为什么会这样?不包含这个构造函数背后的设计决策是什么?char能够直接将 a 转换为字符串,而不必使用填充构造函数,感觉是一个非常自然和直观的想法。

我的目标是能够统一使用chars 和std::strings 。

Nic*_*las 6

在 C 和 C++ 中,char具有双重职责。它既代表一个字符代表一个数字。它被视为整型,这意味着它参与到许多其他整型类型的隐式整数提升,以及其他整型类型的隐式转换。

因为char是重载的,所以在函数接口级别不可能知道用户是否传入了实际的字符(字符文字或类型的变量char)或恰好足够小以适合一个数字文字。char

因此,char在界面中使用时,必须小心与用户提供的内容发生意外冲突。

序列容器类型(在序列中保存与这些元素的值无关的多个元素的类型)通常具有一个采用Ts 计数的构造函数。这是在序列中创建的元素数量,通过值初始化构造(还有一个版本采用 aT用于复制初始化这些元素,这就是您所使用的)。

但是basic_string特别的是;它没有这样的构造函数。如果你尝试这样做std::string s(4);,你会得到一个编译错误。

但是,如果您进行了所需的更改,std::string s(4);则会编译并执行。但它不会你一个由 4 个值初始化的字符组成的序列。它会给你一个包含单个字符且值为 4 的字符串。这是因为整数文字 4 可以char隐式转换为 a。

basic_string与公共序列容器接口的期望不一致已经够糟糕的了。但积极地使其编译但具有完全不同的行为会更糟糕。

此外,您可以使用列表初始化来更明确地获得您想要的内容:

std::string s1{some_char};
std::string s2 = {4}; //converts 4 to `char`
std::string s3 = {other_char};
Run Code Online (Sandbox Code Playgroud)

列表初始化是我们T用 s 序列初始化容器的方式T


Dav*_*ing 5

接受 a 的构造函数将通过隐式转换char接受任何整型,因此这可以工作,但(在典型的现代系统上)会给你. 您可以限制构造函数:std::string(48)"0"

namespace std {
  template<
    class CharT,
    class Traits = char_traits<CharT>,
    class Allocator = allocator<CharT>
  > class basic_string {
  public:
    template<class X, class = enable_if_t<is_same_v<X, CharT>>
    basic_string(X);
    // ...
  };
}
Run Code Online (Sandbox Code Playgroud)

但这似乎不再是一个简单的界面了。