为什么std::to_string没有对std::string进行重载?

16
标题就已经说明了一切。他们为什么选择不使用一个

标签?

namespace std
{
    std::string to_string(const std::string&)
}

重载?

我有一个程序可以通过行索引或行名称查询一些数据;非常适合模板。但是,如果正在访问的行不存在,我尝试构建错误消息时就会出现问题:

template <typename T>
int read(T nameOrIndex)
{
    if (!present(nameOrIndex))
    {
        // This does not compile if T is std::string.
        throw std::invalid_argument("Missing row: " + std::to_string(nameOrIndex));
    }
}

我可以在std命名空间中添加自己的重载,但这并不理想。


2
可能只是因为疏忽而遗漏了。 - Timothy Shields
4
如果T是其他类型之一,你的代码将无法编译。那么其他类型怎么办呢?是否应该有一个返回任意类型字符串的to_string实现?而不是向std添加to_string重载(这是非法的),我会在与read相同的命名空间中创建自己的to_string重载。从那里委托给std::to_string,并从接受std::string const&的重载中直接返回参数。 - Praetorian
2
std::to_string将内置的数字类型转换为字符串。不需要将字符串“转换”为字符串,因为它们已经是字符串。 - Pete Becker
据我所知,to_string基本上是C格式化工具的安全接口,它会将缓冲区和其他内容隐藏起来。对于字符串,确实有一个C格式化说明符%s。因此,显然有一些东西已经丢失了 :) - Chris Beck
@PeteBecker:这将增加一致性并可能简化一些代码。尽管没有必要,但您也可以将整数转换为整数,例如 int x; int y = static_cast<int>(x); - Sebastian Mach
2个回答

14

不要在 std 命名空间中定义自己的接受 std::string 的重载函数,这是一个非常糟糕的解决方案,相反你可以采用以下方法:

#include <iostream>
#include <string>

std::string to_string(const std::string& value)
{
    return value;
}

template <typename T>
void display(T value)
{
    using namespace std;
    std::cout << to_string(value) << std::endl;
}

int main()
{
    display("ABC");
    display(7);
}

1
这段代码没有使用ADL,因为参数具有内置类型。相反,display函数从std中引入名称,以便未限定的查找集中具有std::to_string::to_string - M.M
@M.M,这里的ADL是什么意思? - Marc.2377

1
我不会猜测为什么重载不在标准库中,但是这里有一个简单的解决方案可以使用。不要使用 std::to_string,而是使用 boost::lexical_cast
template <typename T>
int read(T nameOrIndex)
{
  if (!present(nameOrIndex))
    {
      throw std::invalid_argument {
          "Missing row: " + boost::lexical_cast<std::string>(nameOrIndex)
      };
    }
  // …
}

如果您不想依赖Boost,您可以轻松地为此编写自己的函数。
template <typename T>
std::string
to_string(const T& obj)
{
  std::ostringstream oss {};
  oss << obj;
  return oss.str();
}

显然它没有被优化,但对于你的情况可能足够好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接