3
votes

The function I want to run:

struct foo;
void bar(const foo* p = 0);

How I call the function:

auto thread = std::thread(&bar, NULL);

The warning:

foobar.h:223:9: warning: passing NULL to non-pointer argument 2 of ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (*)(const foo*), _Args = {int}]’ [-Wconversion-null]

What am I missing here?

When I call the function with non-NULL argument, the warning goes away.

2
and when you use 0 instead of NULL? - wimh
You should really be using nullptr instead of NULL in C++ >= 11. - cdhowie
In the call? @Wimmel I have changed the prototype, nothing happened. - gsamaras
I have to look into that @cdhowie, never used it before. - gsamaras
@molbdnilo No, _Args is deduced from the arguments supplied to the std::thread constructor, which implies that whatever the NULL macro evaluates to has type int. The definition of NULL is implementation-defined, so we'd have to know how it's defined in OP's case to understand why it has type int. (Typically it's defined as ((void *)0) in older C code. Obviously it has a different definition here -- probably just 0, and 0 is implicitly convertible to any pointer type, but some random int, which is what the 0 becomes as a parameter to std::thread(), cannot.) - cdhowie

2 Answers

5
votes

The trouble is that NULL is a bit ambiguous.
While it is semantically a pointer, it can (and in your implementation is) of integral type.

18.2 Types [support.types]

3 The macro NULL is an implementation-defined C++ null pointer constant in this International Standard (4.10).

4.10 Pointer conversions [conv.ptr]

1 A null pointer constant is an integer literal (2.14.2) with value zero or a prvalue of type std::nullptr_t.
[...]

So your implementation decided to make it plain 0 for backwards-compatibility, but to flag it for extra diagnostics.

Which is actually a laudable decision for promoting portable code.
Though it's a shame noone could hop into a time-machine and just make NULL identical to nullptr in the standard, so the ambiguity does not exist.

To resolve the error, use nullptr instead of NULL or, more involved and not so nice, a pointer of the proper type.

2
votes

The problem is that NULL is a macro with value 0. Template argument deduction deduced the type of NULL as int (as you can see from the end of the warning). Yet NULL is by convention used for pointer arguments, not integral arguments. So the compiler warns you that you're passing a NULL argument to an int parameter. To make things worse, this is technically wrong as that non-const integer 0 argument is no longer guaranteed to be convertable to a null pointer.

The correct solution is nullptr. This is, as the name already hints, a pointer instead of an integer.