2015-05-14 54 views
7

我正在阅读S.Meyers的Effective Modern C++,我发现了一些我无法完全理解的东西。为什么模板内部的类型检查更严格?

第8项解释了为什么nullptr应该优于0NULL。赞成nullptr的主要观点是在超载分辨率下更安全的行为。在实践中,你可以避免指针和整数类型之间的无意混淆,但这不是我的问题的关键。

要到我的实际问题时,请考虑下面的代码,这是基于在本书中使用的例子:

#include <memory> 

class MyClass { 
    int a; 
}; 

// dummy functions that take pointer types 
int f1(std::shared_ptr<MyClass> spw){return 1;}; 
double f2(std::unique_ptr<MyClass> upw){return 1.0;}; 
bool f3(MyClass* pw){return true;}; 

// template that calls a function with a pointer argument 
template<typename FuncType, 
     typename PtrType> 
auto CallFun(FuncType func, PtrType ptr) -> decltype(func(ptr)) 
{ 
    return func(ptr); 
} 

int main() 
{ 
    // passing null ptr in three different ways 
    // they all work fine int this case 
    auto result1 = f1(0);  // pass 0 as null ptr to f1 
    auto result2 = f2(NULL);  // pass NULL as null ptr to f2 
    auto result3 = f3(nullptr); // pass nullptr as null ptr to f3 } 

    // passing null ptr in three different ways through the template 
    // only nullptr works in this case 
    auto result4 = CallFun(f1, 0);   // compile error! 
    auto result5 = CallFun(f2, NULL);  // compile error! 
    auto result6 = CallFun(f3, nullptr); // OK 

    return 0; 
} 

前三直接调用f1f2f3编译罚款或者0NULLnullptr作为空指针。随后的3个调用通过模板函数CallFun执行更加挑剔:您必须使用nullptr,否则将不接受整数类型(0NULL)之间的转换。换句话说,类型检查在模板内部发生时似乎更为严格。有人可以澄清发生了什么吗?

+0

我问完全相同的问题:)请参阅我放的dupe链接,并参见标准报价。 – vsoftco

回答

7

CallFun演绎的PtrType0NULLint类型,不隐式转换为指针类型。

如果你要明白我的意思,只是尝试存储0NULLauto“,第D变量,并调用f1从这些变量的f2。他们不会编译。

0NULL本身隐式转换为指针类型,因为它们是字面值我猜。标准中可能有一些关于它的内容,但我认为你明白了。

+0

值得注意的是'decltype(NULL)'在每个编译器上可能不是'int'。唯一的要求是文字可以隐式转换为任何指针类型,因此'NULL'可以被定义为'nullptr'。 – Pubby

+0

@pubb引用? – Yakk

+2

[support.types]/3:“宏NULL是实现定义的C++空指针常量”。 [conv.ptr]/1:“空指针常量是一个整数字面值,其值为零或类型为”std :: nullptr_t“的前值”。 – TartanLlama