我有一个功能
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 ==========
答案 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
的值无法隐式转换为指针。