运算符<< (流输出)为nullptr

时间:2015-07-01 15:00:24

标签: c++ c++11 stl nullptr stream-operators

考虑一段通用C ++代码,如果它们不相等,它们会向流输出其参数的值:

mktime()

这只是一个例子,真实代码在将消息写入字符串流后抛出异常。 这适用于2个整数,2个指针等,用于定义流#define LOG_IF_NE(a, b) if(a != b) { \ std::cerr << "Failed because (" << ##a << "=" << (a) << \ ") != (" << ##b << "=" << (b) << ")"; \ }

operator <<

int g_b; int f(int a) { LOG_IF_NE(a, g_b); // implementation follows } 的一个参数为LOG_IF_NE时,会出现问题:MSVC ++ 2013编译器提供nullptr

error C2593: 'operator <<' is ambiguous

问题发生是因为int *pA; int g() { LOG_IF_NE(pA, nullptr); } 具有特殊类型,并且在该类型的STL中未定义nullptrhttps://stackoverflow.com/a/21772973/1915854的答案建议为operator <<

定义operator <<
std::nullptr_t

这是解决问题的正确方法吗? C ++ 11 / STL中的错误是//cerr is of type std::ostream, and nullptr is of type std::nullptr_t std::ostream& operator << (std::ostream& os, std::nullptr_t) { return os << "nullptr"; //whatever you want nullptr to show up as in the console } 没有定义operator<<吗?是否可以在C ++ 14/17中修复?或者是故意这样做的(因此,nullptr_t的私人定义可能会有陷阱)?

2 个答案:

答案 0 :(得分:3)

这是LWG #2221,建议:

  

明显的库解决方案是添加nullptr_t重载,其定义类似于

template<class C, class T>
basic_ostream<C, T>& operator<<(basic_ostream<C, T>& os, nullptr_t) 
{ 
  return os << (void*) nullptr; 
}
     

我们也可以考虑在核心级别解决这个问题:添加一个特殊用语语言规则,解决所有写入f(nullptr)并且f在多个指针类型上重载的情况。 (在这种情况下,或许是决胜因者说void*是首选。)

它不是在C ++ 14中,我不知道它是否会成为C ++ 17。修复自己是一个非常容易的问题,因此就标准的变化而言,它并不是特别优先考虑的问题。正如你在问题中所说的那样 - 它只是一个3行功能。

答案 1 :(得分:1)

我认为这可能是故意的,因为nullptr是它自己的价值。在这种情况下默默地接受它可能被视为可能违反先决条件和不变量。

nullptr是一个初始化指针的值,用于检测它是否尚未初始化。因此,通过这种逻辑,无论如何实际使用它应该是明确的并且记录在案以防止滥用和潜在的安全漏洞。简单地重载操作员无论如何都要将其打印出来。但

如果你正在检查不变量和程序逻辑以及其他所有内容的明确定义的输出,那么在调试环境(你的宏会调用home)中使用带有条件编译的断言会更有意义。

这基本上归结为一个设计点: 处理可以从 中最好地恢复的错误。你的宏测试了不等式,但是如果它发现了nullptr,那个宏处理那个错误就没有意义了,所以回到异常处理会更有意义,所以可以抛出一个可以处理的问题从nullptr恢复。否则,您将允许程序处于不一致或不安全的状态。

编辑:刚看到您实际上正在使用异常处理。嵌套的try / catch可能是最佳的,因为你可以捕获它们可以处理的两个错误。