I have a function
int f(std::shared_ptr<MyClass> sptr);
After that I write the following template to be able to call it (and some other) functions:
template <typename Func, typename ArgType>
auto call(Func func, ArgType arg) -> decltype(func(arg))
{
return func(arg);
}
Why do I get an error in the third line when I try to use this template with NULL?
auto r0 = f(0); // OK
auto r1 = call(f, nullptr); // OK
auto r2 = call(f, NULL); // ERROR! WHY??
1>------ Build started: Project: ConsoleApplication1, Configuration: Debug x64 ------
1> main.cpp
1>main.cpp(245): error C2893: Failed to specialize function template 'unknown-type call(Func,Arg)'
1> With the following template arguments:
1> 'Func=int (__cdecl *)(std::shared_ptr<MyClass>)'
1> 'Arg=int'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Uses of NULL other than comparing with a pointer (like using it to represent the nul byte at the end of a string) won't work with nullptr . In some cases, NULL is #define NULL 0 , as the integer constant 0 is special-cased in C and C++ when you compare it with pointers.
You cannot pass a null pointer parameter value by specifying a value of null or "" in the external function call, as these both produce a pointer to an empty string instead of a null pointer. To pass a null pointer parameter value, specify a value of zero (0) in the external function call.
- In the context of a direct-initialization, a bool object may be initialized from a prvalue of type std::nullptr_t, including nullptr. The resulting value is false.
A reference shall be initialized to refer to a valid object or function. [Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer, which causes undefined behavior.
The clue is here:
Arg=int
NULL must be a null pointer constant which, before C++11, meant it must be an integer constant with value zero. In your implementation, it has type int, and is probably the literal 0.
So the template parameter is deduced as int, which is not convertible to shared_ptr, hence the error.
As for the others:
auto r0 = f(0); // OK
The literal 0 can be treated as a null pointer constant, and converted to shared_ptr, if passed directly to the function. Within the call, the argument isn't a literal, but a variable of type int, which can't be converted.
auto r1 = call(f, nullptr); // OK
nullptr has its own type, which is convertible to shared_ptr.
Because in C++ NULL is usually defined as 0 which is an int. So the template type ArgType is deduced to be an int and you can't convert an int to a std::shared_ptr.
Note that it works for e.g. f(0) (and should then work for f(NULL)) but that's because the compiler knows that 0 in that case is a null-pointer. In the call function, the compiler have no idea what value the variable arg will have, only that it's of type int which can't be converted implicitly to a pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With