2015-05-14 57 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