首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >使用户定义的类std::to_string-able

使用户定义的类std::to_string-able
EN

Stack Overflow用户
提问于 2015-10-28 19:10:34
回答 8查看 24.8K关注 0票数 42

我知道这似乎太过了Java或C#。但是,是否有可能/很好/明智地使我自己的类作为函数std::to_string的输入有效?示例:

代码语言:javascript
代码运行次数:0
运行
复制
class my_class{
public:
std::string give_me_a_string_of_you() const{
    return "I am " + std::to_string(i);
}
int i;
};

void main(){
    my_class my_object;
    std::cout<< std::to_string(my_object);
}

如果没有这样的事情(我认为),最好的方法是什么?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2015-10-28 19:22:06

首先,一些ADL帮助:

代码语言:javascript
代码运行次数:0
运行
复制
namespace notstd {
  namespace adl_helper {
    template<class T>
    std::string as_string( T&& t ) {
      using std::to_string;
      return to_string( std::forward<T>(t) );
    }
  }
  template<class T>
  std::string to_string( T&& t ) {
    return adl_helper::as_string(std::forward<T>(t));
  }
}

notstd::to_string(blah)将在to_string(blah)的作用域内对std::to_string进行ADL查找.

然后我们修改您的类:

代码语言:javascript
代码运行次数:0
运行
复制
class my_class{
public:
  friend std::string to_string(my_class const& self) {
    return "I am " + notstd::to_string(self.i);
  }
  int i;
};

现在notstd::to_string(my_object)找到了合适的to_stringnotstd::to_string(7)也找到了。

随着触摸更多的工作,我们甚至可以支持.tostring()方法的类型自动检测和使用。

实例化

票数 26
EN

Stack Overflow用户

发布于 2015-10-28 19:20:28

什么是‘最好’的方式是一个悬而未决的问题。

有几种方法。

首先要说的是,不允许为自定义类型重载std::to_string。我们可能只为自定义类型专门化std命名空间中的模板函数和类,而std::to_string不是模板函数。

也就是说,处理to_string的一个好方法很像一个操作符或swap的实现。也就是说,允许依赖于参数的查找来完成工作。

因此,当我们想要将某些内容转换为字符串时,我们可以编写:

代码语言:javascript
代码运行次数:0
运行
复制
using std::to_string;
auto s = to_string(x) + " : " + to_string(i);

假设x是命名空间Y中X类型的对象,而我是int,那么我们可以定义:

代码语言:javascript
代码运行次数:0
运行
复制
namespace Y {

  std::string to_string(const X& x);

}

这意味着:

调用to_string(x)实际上选择了Y::to_string(const Y::X&),并且

调用to_string(i)选择std::to_string(int)

更进一步,您可能希望to_string与operator<<做很多相同的事情,这样就可以用另一种方式编写一个:

代码语言:javascript
代码运行次数:0
运行
复制
namespace Y {

  inline std::ostream& operator<<(std::ostream& os, const X& x) { /* implement here */; return os; }

  inline std::string to_string(const X& x) {
    std::ostringstream ss;
    ss << x;
    return ss.str();
  }
}
票数 29
EN

Stack Overflow用户

发布于 2015-10-28 19:17:30

您可以在自己的名称空间(例如,to_string )中定义自己的foo

代码语言:javascript
代码运行次数:0
运行
复制
namespace foo {
   std::string to_string(my_class const &obj) {
     return obj.string give_me_a_string_of_you();
   }
}

并将其用作:

代码语言:javascript
代码运行次数:0
运行
复制
int main(){
    my_class my_object;
    std::cout<< foo::to_string(my_object);
}

不幸的是,您无法在命名空间to_string中定义您自己的std版本,因为它符合标准17.6.4.2.1标准的名称空间std namespace.std ( define )

如果C++程序向名称空间std或命名空间std中的命名空间添加声明或定义(除非另有规定),则该程序的行为是未定义的。程序只有在声明依赖于用户定义的类型,且该专门化满足原始模板的标准库要求且不明确禁止的情况下,才能为任何标准库模板添加模板专门化。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33399594

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档