教 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 子句中)。
两个问题:
- 我可以通过从我重新定义的版本中调用原始
operator<<
来打破无限递归。我该怎么做呢? (这里缺乏 C++ 技能...)
- 是否有更好(更惯用)的方法来实现我想要的?
一个快速的解决方案是改用 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);
}
可以在全局命名空间中重载这些运算符(尽管我不确定标准是否允许这样做),但我会在您使用它们的命名空间内执行此操作。
在我的程序中,我处理有时为 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 子句中)。 两个问题:
- 我可以通过从我重新定义的版本中调用原始
operator<<
来打破无限递归。我该怎么做呢? (这里缺乏 C++ 技能...) - 是否有更好(更惯用)的方法来实现我想要的?
一个快速的解决方案是改用 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);
}
可以在全局命名空间中重载这些运算符(尽管我不确定标准是否允许这样做),但我会在您使用它们的命名空间内执行此操作。