为什么std :: to_string()没有模板化?

时间:2020-07-07 08:01:25

标签: c++ templates libstdc++

如上所述,here std::string不是模板函数,而是标准选择使用函数重载为不同类型提供此函数。我的问题是为什么在这种情况下,当模板/专业化对我来说更有意义时,为什么要使用重载?考虑一下,如果该标准定义了以下内容:

template <typename T>
std::string std::to_string(const T& v);

然后,我们可以为程序中的任何类型自由添加特殊化以符合此签名,因此C ++将具有一种统一的方式将类型转换为人类可读的字符串。为什么不这样做呢?当前设计背后的想法是什么?

编辑1:

我对当前设计的主要批评是不允许在std上添加重载,因此我们不能编写类似std:to_string(object-that-is-of-user-defined-types)的内容,而不得不依靠定义{{1} }放在自己的命名空间中,并记住在何处使用其版本或to_string()版本取决于他们正在处理的类型...这听起来让我感到头疼。

我真的很喜欢Python(或其他一些语言)的一件事是,您可以通过实现一些魔术方法使自己的类型像本机类型一样工作。我认为这个问题的根本原因在于,为什么C ++决定禁止人们为其自己的类型实现std,从而禁止我们在任何地方都遵循相同的接口。

对于诸如std::to_string()hash这样的常见事物,在语言/ to_string()级别上具有单个界面然后期望用户遵循该界面不是更好,而不是有多个接口?

2 个答案:

答案 0 :(得分:5)

为什么C ++决定禁止人们为自己的类型实现std::to_string

这是ADL有用的地方。我们已经有了使用std::swap正确执行此操作的示例,该示例已在许多代码库中成功完成:

template <typename T>
void swap_example(T & a, T & b) {
    using std::swap;
    swap(a, b);
}

如果在其中声明了命名空间T具有兼容的swap()函数,而需要重载std::swap,则此方法有效。我们可以使用std::to_string做同样的事情:

template <typename T>
void to_string_example(T const & x) {
    using std::to_string;
    to_string(x);
}

如果声明的命名空间T具有可以接受to_string参数的T const &函数,这同样可以工作。例如:

namespace example {
    class Foo;

    std::string to_string(Foo const &);
}

to_string_example(example::Foo{})将找到并使用相应的example::to_string函数。


记住在哪里使用他们的版本或std版本取决于他们正在处理的类型...这听起来让我很头疼。

如果这确实让您头疼,您可以将ADL隐藏在项目中的实用程序功能后面:

template <typename T>
std::string adl_to_string(T const & x) {
    using std::to_string;
    return to_string(x);
}

现在,您可以在各处使用adl_to_string(...)而不是std::to_string(...),而不必考虑它。

答案 1 :(得分:2)

这听起来可能有点无聊,但是export class CustomerEditComponent implements OnInit { constructor() {} options: CityMaster[]; selectedOption: string; ngOnInit(): void { this.options = [ { id: 1, cityName: "Mumbai" }, { id: 2, cityName: "Delhi" }, { id: 3, cityName: "Banglore" }, { id: 4, cityName: "Lucknow" } ]; } } 的目的是像您曾经使用过std::to_string一样进行格式化,并且由于sprintf仅支持一组有限的类型,所以这也是正确的sprintf。无需使其成为模板。

正如this answer中详细解释的那样,设计没有您认为有的限制。您仍然可以提供自己的std::to_string,并且在使用正确的名称限定来启用ADL的代码中,将调用您的重载。为此,没有必要向foo::to_string(foo::bar&)添加重载。

相关问题