【问题标题】:Printing textual representation of objects打印对象的文本表示
【发布时间】:2014-10-20 03:26:58
【问题描述】:

我对 C++ 比较陌生。如果不正确,请原谅我的术语。我试图四处寻找我的问题的答案,但找不到(可能是因为我无法正确表达我的问题)。如果有人可以帮助我,我将不胜感激。

我正在尝试编写一个类来创建可能包含对象或本机类型的文本表示的字符串。基本上,我有

private:
    stringstream ss;


public:
    template< typename T >
    Message& operator<<( const T& value ) {
        ss << value;
        return *this;
    }

重载的 T 类似于int 或者如果类T 定义了方法operator std::string(),我认为我的编译器对此很好。但是,如果T 是某种类型,例如vector&lt;int&gt;,那么它就不再有效,因为vector&lt;int&gt; 没有定义operator std::string()

我是否可以重载这个运算符,如果T 定义了operator std::string(),那么我打印文本表示,如果没有,我只打印它的地址?

谢谢。

【问题讨论】:

    标签: c++ templates operator-overloading


    【解决方案1】:

    这可以通过构建此处描述的has_insertion_operator 类型特征来实现:https://stackoverflow.com/a/5771273/4323

    namespace has_insertion_operator_impl {
    typedef char no;
    typedef char yes[2];
    
    struct any_t {
      template<typename T> any_t( T const& );
    };
    
    no operator<<( std::ostream const&, any_t const& );
    
    yes& test( std::ostream& );
    no test( no );
    
    template<typename T>
    struct has_insertion_operator {
      static std::ostream &s;
      static T const &t;
      static bool const value = sizeof( test(s << t) ) == sizeof( yes );
    };
    }
    
    template<typename T>
    struct has_insertion_operator :
      has_insertion_operator_impl::has_insertion_operator<T> {
    };
    

    有了这些,剩下的就相对简单了:

    class Message
    {
      std::ostringstream ss;
    
    public:
      template< typename T >
      typename std::enable_if<has_insertion_operator<T>::value, Message&>::type
      operator<<( const T& value ) {
        ss << value;
        return *this;
      }
    
      template< typename T >
      typename std::enable_if<!has_insertion_operator<T>::value, Message&>::type
      operator<<( const T& value ) {
        ss << &value;
        return *this;
      }
    };
    

    即如果定义了插入操作符,则打印该值,否则打印其地址。

    这不依赖于定义的转换为std::string 运算符——您只需要使用operator &lt;&lt; 确保您的T 实例是“可打印的”(通常在相同的范围内实现,其中每个@ 987654328@ 已定义,例如命名空间或全局范围)。

    【讨论】:

      【解决方案2】:

      这是一个示例 - 使用一些自定义特征将转换运算符转换为 std::string 和流式运算符:

      #include <iostream>
      #include <string>
      
      template <class T>
      struct traits
      {
          template <typename Q>
          static auto hos(Q*) -> decltype(std::declval<const Q>().operator std::string());
      
          static char hos(...);
      
          constexpr static bool has_operator_string =
              sizeof hos((T*){0}) != 1;
      
          // ----
      
          template <typename Q>
          static auto isab(Q*) -> decltype(std::cout << std::declval<const Q>());
      
          static char isab(...);
      
      
          constexpr static bool is_streamable =
              sizeof isab((T*){0}) != 1;
      };
      
      struct S
      {
          template <typename T>
          typename std::enable_if<
                       traits<T>::has_operator_string,
                       S&>::type
          operator<<(const T& value)
          {
              std::cout << "string() " << value.operator std::string() << '\n';
              return *this;
          }    
      
          template <typename T>
          typename std::enable_if<!traits<T>::has_operator_string && traits<T>::is_streamable, S&>::type
          operator<<(const T& value)
          {
              std::cout << "<< " << value << std::endl;
              return *this;
          }
      
          template <typename T>
          typename std::enable_if<
                       !traits<T>::has_operator_string &&
                       !traits<T>::is_streamable,
                       S&>::type
          operator<<(const T& value)
          {
              std::cout << "T& @" << &value << std::endl;
              return *this;
          }
      };
      
      struct X
      {
          operator std::string() const { return "hi"; }
      };
      
      struct Y
      {
      
      };
      
      int main()
      {
          std::cout << "> main()" << std::endl;
      
          std::cout << "X() ";
          S() << X();
      
          Y y;
          std::cout << "Y y; ";
          S() << y;
      
          std::cout << "Y() ";
          S() << Y();
      
          std::cout << "\"text\" ";
          S() << "text";
          std::cout << "< main()" << std::endl;
      }
      

      【讨论】:

        猜你喜欢
        • 2013-06-23
        • 2021-05-12
        • 2019-04-26
        • 2013-03-15
        • 1970-01-01
        • 2020-08-08
        • 2011-02-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多