2016-10-30 16 views
3

我想圍繞SFINAE包裹我的頭。 我們正在使用它來檢查一個班級是否有一種名爲「乘客」的方法。SFINAE C++方法檢查

通過一些在線示例,我們構建了以下模板類。

#ifndef TYPECHECK 
#define TYPECHECK 

#include "../Engine/carriage.h" 

namespace TSS{ 

template<typename T> 
class has_passengers{ 
private: 
    typedef char one; 
    typedef struct{char a[2];} two; 

    template<typename C> static one test(decltype(&C::Passengers)); 
    template<typename C> static two test(...); 
public: 
    static bool const value = sizeof(test<T>(0)) == sizeof(one); 
}; 

template<typename T> 
struct CarriageTypeCheck{ 
    static_assert(has_passengers<T>::value, "Train initialized with illegal carriage"); 
}; 

} 


#endif // TYPECHECK 

我得到如何選擇任一兩個測試方法的一部分,但我不明白的是爲什麼test<T>與0在下面的行初始化:

static bool const value = sizeof(test<T>(0)) == sizeof(one); 

我可以沒有看到0對於檢查工作的重要性。 另一件事 - 爲什麼使用decltype?

+0

你不檢查班級是否有成員功能'乘客'。你正在檢查它是否有一個「乘客」成員,這可能是一個功能,但不一定是。 – krzaq

+0

好點!謝謝! –

回答

2

第一個重載函數(可能)將一個指向類方法的指針作爲參數。由於C++的C遺留,值0可轉換爲NULL指針或nullptr。因此,如果SFINAE沒有發出第一個重載函數,則test<T>(0)變爲有效的函數調用,並且其sizeof等於sizeof(one)。否則,這將解決第二個重載的函數調用。

以及爲什麼decltype被使用的簡短答案:否則它不會是有效的C++。在函數聲明中,函數的參數必須是類型,指定函數的參數類型。 &C::Passengers不是一個類型(在其預期用途的上下文中),所以這將不是有效的C++。 decltype()自動獲得其參數的類型,使其有效的C++。

+0

好的。但是如果T沒有乘客,這不等於'sizeof(two)'嗎?然後調用將是測試(空指針),然後大小將是2? –

+0

@BenjaminLarsen如果T沒有乘客,輸入扣減將失敗,函數模板將被忽略;這就是SFINAE的工作原理。沒有這樣的規則來傳遞空指針,沒有SFINAE,你會得到一個complie錯誤。 – songyuanyao

+0

我想我現在明白了!感謝你們。 –

1

我看不到0對於檢查工作是如何重要。

由於0可以用作這兩種情況的參數(即,兩個重載test);用於成員指針(視爲空指針)和可變參數...

另一件事 - 爲什麼使用decltype?

decltype用於描述部件的指針作爲test參數的類型(即&C::Passengers)。