Consider a piece of generic C++ code which outputs to a stream the values of its arguments in case they are not equal:
#define LOG_IF_NE(a, b) if(a != b) { \
std::cerr << "Failed because (" << ##a << "=" << (a) << \
") != (" << ##b << "=" << (b) << ")"; \
}
This is just an example, the real code throws an exception after writing message to a string stream.
This works fine for 2 integers, 2 pointers, etc. for what stream operator <<
is defined.
int g_b;
int f(int a)
{
LOG_IF_NE(a, g_b);
// implementation follows
}
A problem happens when one of the arguments to LOG_IF_NE
is nullptr
: MSVC++2013 compiler gives error C2593: 'operator <<' is ambiguous
.
int *pA;
int g()
{
LOG_IF_NE(pA, nullptr);
}
The problem happens because nullptr
has a special type and operator <<
is not defined in the STL for that type. An answer at https://stackoverflow.com/a/21772973/1915854 suggests to define operator <<
for std::nullptr_t
//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
}
Is it the right way to solve the problem? Isn't it a bug in C++11/STL that operator<<
is not defined for nullptr_t
? Is a fix expected in C++14/17? Or was it done on purpose (therefore one's private definition of operator<<
could have a pitfall)?
This is LWG #2221, which proposes:
The obvious library solution is to add a
nullptr_t
overload, which would be defined something liketemplate<class C, class T> basic_ostream<C, T>& operator<<(basic_ostream<C, T>& os, nullptr_t) { return os << (void*) nullptr; }
We might also consider addressing this at a core level: add a special-case language rule that addresses all cases where you write
f(nullptr)
andf
is overloaded on multiple pointer types. (Perhaps a tiebreaker saying thatvoid*
is preferred in such cases.)
It isn't in C++14, I don't know whether or not it will make it into C++17. It is a very easy problem to fix yourself, so it's not particularly high priority as far as standards changes go. As you said yourself in the question - it's just a 3 line function.