为什么函数模板不理解NULL但与nullptr一起工作?

时间:2015-01-27 14:04:56

标签: c++ c++11

我有一个功能

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

2 个答案:

答案 0 :(得分:9)

线索在这里:

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

答案 1 :(得分:3)

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

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