2011-09-14 34 views
3

編輯:對不起,這個問題是重複的。原文:SFINAE to check for inherited member functions如何設置一個成員,如果它存在?

我有一個模板函數(在用於測試類):

template <class CHandler> 
void InitHandler(CHandler &handler) 
{ 
    handler.setId(0); 
    handler.SetCache(m_pCache.get()); 
    handler.m_pScience = m_pScience; 
} 

然而,它是可能的,這功能可以與不具有m_pScience模板參數來調用會員。

我可以使用模板元編程來設置此成員是否存在?

+2

如果你將成爲唯一一個將其維持下去的人:) –

+0

我幾乎肯定這隻會導致比解決更多的麻煩。我想不出有什麼辦法可以做到這一點,而不會涉及對界面的更改,這意味着您應該重新考慮您在此處列出的設計。 – tenfour

+0

如果目標類(在本例中爲「CHandler」)沒有公共m_pScience成員,則編譯器會在模板實例化時通知您。 –

回答

5

Reimagining這樣的回答:How to detect whether there is a specific member variable in class?

template<typename T> struct Hasm_pScience 
{ 
    struct Fallback { int m_pScience; }; // introduce member name "m_pScience" 
    struct Derived : T, Fallback { }; 

    template<typename C, C> struct ChT; 

    template<typename C> static char (&f(ChT<int Fallback::*, &C::m_pScience>*))[1]; 
    template<typename C> static char (&f(...))[2]; 

    static bool const value = sizeof(f<Derived>(0)) == 2; 
}; 

struct A { float m_pScience; }; 
struct B { int X; }; 

int main(int argc, _TCHAR* argv[]) 
{ 
    std::cout << Hasm_pScience<A>::value << std::endl; // 1 
    std::cout << Hasm_pScience<B>::value << std::endl; // 0 

    return 0; 
} 

總的原則,以谷歌爲SFINAE(替換故障不是一個錯誤)。

+0

This讓我們檢查它,但不要有條件地做任何事情,因爲如果你做了void func(){if(Hasm_pScience :: value){a.pScience = 1;}},如果Hasm評估爲錯誤。 –

1

通常,當您需要某個模板中的某個成員時,您應該強制該模板的用戶實施該模板,即使這些用戶沒有任何用途。常見示例是stl setmap,您需要定義一個operator <

有許多(適當的)方法可以做你想做的事情,但它們都涉及到要求模板的用戶有一個特定的成員變量或函數。

你也可以有兩個模板,一個用於m_pScience,另一個用於那些沒有的模板,但我不建議這樣做。這樣,你必須確保兩個模板之間的代碼是一致的。

相關問題