Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why function template does not understand NULL but works with nullptr?

Tags:

c++

c++11

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 ==========
like image 383
Serebrov Avatar asked Jan 27 '15 14:01

Serebrov


People also ask

Is nullptr compatible with null?

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.

Can we pass null pointer to a function?

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.

Does nullptr return false?

- 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.

Can reference point to null?

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.


2 Answers

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.

like image 72
Mike Seymour Avatar answered Oct 31 '22 17:10

Mike Seymour


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.

like image 42
Some programmer dude Avatar answered Oct 31 '22 19:10

Some programmer dude