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