为什么函数模板不理解 NULL 但可以使用 nullptr?

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

我有一个功能

int f(std::shared_ptr<MyClass> sptr);

之后,我编写了以下模板,以便能够调用它(和其他一些)函数:

template <typename Func, typename ArgType>
auto call(Func func, ArgType arg) -> decltype(func(arg))
{
    return func(arg);
}

当我尝试将此模板与 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 ==========

线索在这里:

Arg=int

NULL 必须是一个空指针常量,在 C++11 之前,这意味着它必须是一个值为零的整数常量。在您的实现中,它的类型为 int,并且可能是文字 0.

因此模板参数被推导为int,无法转换为shared_ptr,因此出现错误。

至于其他:

auto r0 = f(0); // OK

文字 0 可以被视为空指针常量,如果直接传递给函数,则转换为 shared_ptr。在call中,参数不是文字,而是int类型的变量,无法转换。

auto r1 = call(f, nullptr); // OK

nullptr 有自己的类型,可以转换为 shared_ptr.

因为在 C++ 中 NULL 通常被定义为 0,这是一个 int。因此模板类型 ArgType 被推断为 int 并且您无法将 int 转换为 std::shared_ptr.

请注意,它适用于例如f(0)(然后应该为 f(NULL) 工作)但那是因为编译器知道 0 在这种情况下是一个空指针。在 call 函数中,编译器不知道变量 arg 会有什么值,只知道它的类型 int 不能隐式转换为指针。