为什么std::to_string()没有模板化
Why is std::to_string() not templated?
如前所述,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)
的内容,必须在它们自己的命名空间中定义to_string()
,并记住在哪里使用它们的版本或std
版本取决于它们处理的类型。。。这听起来让我头疼。
我真正喜欢Python(或其他一些语言(的一点是,通过实现一些神奇的方法,你可以让自己的类型像原生类型一样工作。我认为这个问题的根本原因是,为什么C++决定不允许人们为自己的类型实现std::to_string()
,从而禁止我们在任何地方都遵循相同的接口。
对于像hash
或to_string()
这样的常见事物,在语言/stdlib
级别上有一个单独的接口,然后期望用户遵守该接口,而不是有多个接口,这不是更好吗?
为什么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
具有可以接受T const &
参数的to_string
函数,则这同样有效。例如:
namespace example {
class Foo;
std::string to_string(Foo const &);
}
CCD_ 19将找到并使用相应的CCD_。
记住在哪里使用他们的版本或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(...)
,而不必考虑它
这听起来可能有点无聊,但std::to_string
的目的是将格式设置为使用sprintf
,并且由于sprintf
仅支持有限的类型集,因此std::to_string
也是如此。没有必要将其作为模板。
正如这个答案中详细解释的那样,设计并没有你认为的限制。您仍然可以提供自己的foo::to_string(foo::bar&)
,并且在使用名称的适当限定来启用ADL的代码中,您的重载将被调用。为此,没有必要向std
添加过载。
- std::bind to void* to std::function
- std::time_point from and to std::string
- "No suitable conversion function from 'std::string' to 'const char *' exists"
- Port pthread_cond_broadcast to std::atomic
- from std::vector to adept::avector
- File to std::string_view
- 如何修复以下错误"no match for call to '(std::tr1::shared_ptr<_iobuf*>) (FILE*&)'"
- std::map to std::list leads to SIGSEGV
- std::bind to a std::variant 包含多个 std::函数类型
- NSMutableArray to std::vector
- 将 2D 数组插入 std::vector 时"cannot convert from 'const GLfloat [12]' to '_Objty'"错误消息
- 使用 std::min "no matching function for call to ‘min(<brace-enclosed initializer list>)’"时出错
- 返回"Cannot convert from 'std::ofstream {aka std::basic_ofstream<char>}' to bool"错误
- reinterpret_cast std::function* to and from void*
- std::string to std::regex
- 使用命名空间 std 时C++ "Reference to overloaded function"错误
- Copy std::vector to boost::interprocess::vector
- BOOST :: lexical_cast to std ::字符串失败
- C++ std::vector to JSON Array with rapidjson
- 最快的方式 std::vector<Derived> to std::vector<Base>