When using the literal 0 in C++, the compiler can't disambiguate between pointer and nullptr_t overloads of a function.
Code that illustrates the problem:
struct Bar {};
void foo(Bar*) {
std::cout << "Bar*" << std::endl;
}
void foo(std::nullptr_t) {
std::cout << "nullptr_t" << std::endl;
}
TEST(NullPtrTest, ambiguity) {
foo(nullptr); // OK
foo(0); // ERROR
}
With Visual Studio 2019:
error C2668: '`anonymous-namespace'::foo': ambiguous call to overloaded function
message : could be 'void `anonymous-namespace'::foo(std::nullptr_t)'
message : or 'void `anonymous-namespace'::foo(`anonymous-namespace'::Bar *)'
message : while trying to match the argument list '(int)'
With GCC 9:
Test.cpp: In member function ‘virtual void {anonymous}::NullPtrTest_ambiguity_Test::TestBody()’:
Test.cpp:425:8: error: call of overloaded ‘foo(int)’ is ambiguous
425 | foo(0); // ERROR
| ^
Test.cpp:415:6: note: candidate: ‘void {anonymous}::foo({anonymous}::Bar*)’
415 | void foo(Bar*) {
| ^~~
Test.cpp:419:6: note: candidate: ‘void {anonymous}::foo(std::nullptr_t)’
419 | void foo(std::nullptr_t) {
| ^~~
What's a good way to fix this?
Things that I don't want to do:
- Replace
0literal withnullptreverywhere. There are just way too many instances in our legacy code base. - Add an
intorlong(or similar) overload. Since0would be the only valid integer value, you would have to add a runtime check, and it would be ugly. - Remove the
nullptr_toverload and check the value in the pointer overload at runtime. This works, and isn't terrible, but it prevents us from having an optimized implementation for null constants.
Thanks!
Clarifications:
- We're using C++14. However, these functions are used by a lot of code that predates C++11.
- The particular use case is to provide an optimized
constexprimplementation whennullptror0is used. The general pointer implementation will still have to check for null values. Thenullptr_toverload isn't really necessary, but it would be nice. - I'm mainly asking about this to see if there is some option that I'm not considering.