教 cout 优雅地处理空指针

teach cout to handle null pointers gracefully

在我的程序中,我处理有时为 NULL 的 C 风格字符串(类型为 char *)。我想教 cout 优雅地处理这些问题(即打印“(null)”而不是段错误)。

我的第一次尝试:

ostream& operator<< (ostream &out, const char *p_str) {
    if (p_str == nullptr)
        out << "(null)";
    else
        out << p_str;
    return out;
}

不起作用,因为它会导致无限递归(在 if 和 else 子句中)。 两个问题:

  1. 我可以通过从我重新定义的版本中调用原始 operator<< 来打破无限递归。我该怎么做呢? (这里缺乏 C++ 技能...)
  2. 是否有更好(更惯用)的方法来实现我想要的?

一个快速的解决方案是改用 std::basic_ostream<>::write 成员函数

if (p_str == nullptr)
    out.write("(null)", 6);
else
    out.write(p_str, std::strlen(p_str)); // need to #include <cstring> for std::strlen
return out;

字符串的原始输出运算符是 namespace std 中定义的非成员,如

namespace std {
  template< class CharT, class Traits >
  basic_ostream<CharT,Traits>& operator<<(basic_ostream<CharT,Traits>&, const CharT*);

  template< class CharT, class Traits >
  basic_ostream<CharT,Traits>& operator<<(basic_ostream<CharT,Traits>&, const char*);

  template< class Traits> 
  basic_ostream<char,Traits>& operator<<(basic_ostream<char,Traits>&, const char*);

  template< class Traits >
  basic_ostream<char,Traits>& operator<<(basic_ostream<char,Traits>&, const signed char*);

  template< class Traits >
  basic_ostream<char,Traits>& operator<<(basic_ostream<char,Traits>&, const unsigned char*);
}

并被 ADL 发现。但是你当然可以像这样显式地调用它们(回想一下 std::ostream 只是 std::basic_ostream<char,std::char_traits<char>> 的类型定义)

inline std::ostream& operator<< (std::ostream &out, const char *p_str)
{  
  return std::operator<< (out, p_str==nullptr? "(null)" : p_str);
}

可以在全局命名空间中重载这些运算符(尽管我不确定标准是否允许这样做),但我会在您使用它们的命名空间内执行此操作。