制作c ++课程的最佳实践" Showable" (字符串,ostream)

时间:2015-10-21 21:26:36

标签: c++ c++11 c++14

我有一个价值语义课,我想成为"可展示的"与Haskells Show类的意义相同,或者Python提供了通用的__str__()函数。

在c ++中:

  • 我可以重载operator<<(ostream&, ...),因此我可以将我的课程输出到例如cout
  • 我可以重载operator std::string()所以我的类转换为 std :: string
  • 我可以重载operator const char*(),以便我的类转换为 const char *。
  • 我可以写一个str()成员,或to_string(...)免费功能

这些功能中的每一个都可以用另一个来定义。一个选项比其他选项更好吗?这些都是选择吗?在c ++ 11/14/17中,最优雅的方法是什么?

2 个答案:

答案 0 :(得分:8)

这个问题将在几分钟内搁置,但我仍然会在这里分享我的想法。

首先,我们可以从列表中删除const char * / std :: string()运算符重载。如果类不是字符串,则它不应该可转换为字符串,并且序列化启用不会使您的类成为字符串。

对于str()to_stringoperator <<,它们非常相同。但是,因为对于任何复杂的类,to_string()和str()很可能在内部使用ostreams,我相信,operator <<是最好的选择。

答案 1 :(得分:2)

我不知道这是否是最佳做法,但......

  1. 用于调试我总是定义operator<<,它以文本形式提供汇总输出(这意味着可以很容易地将对象流式传输到日志文件)

  2. 对于格式化输出我可能会选择在自由函数方面实现这一点:detail::x_detail_writer write_details(const X&)然后给detail::x_detail_writer(这是一个仿函数)operator<< overload

  3. 除了to_stringoperator<<表示最简单的对象外,其他任何事情都是如此。

  4. 为了帮助调试输出,我们有一个辅助类,如下所示:

    template<class T>
    struct make_writeable {
      friend std::ostream& operator<<(std::ostream& os, const T& t) {
        // example prefix...
        os << demangle(typeid(T).name()) << "{";
        t.write(os);
        // example postfix:
        os << " }";
        return os;
      }
    };
    

    然后从中派生出一些类,并给它一个名为write的成员函数:

    struct X : make_writeable<X>
    {
      void write(std::ostream& os) const {
        // write out members here. they will appear within the prefix and postfix
      }
    };