2012-02-07 43 views
1

我想編寫一個模板函數來檢查一些Timestamp屬性(類繼承自Timed),但也必須適用於沒有時間戳的類型。我發現的最好的(也是相當醜陋的)解決方案如下:根據參數類型製作模板功能代碼的最簡單方法是什麼

class Timed { 
    protected: 
    int mTime;   
    public: 
    explicit Timed(int time=0): mTime(time){} 
    int getT() const {return mTime;} 

}; 

template<typename T> 
bool checkStale(T const* ptr) const { 
    return checkStaleImp(ptr, boost::is_base_of<Timed, T>()); 
} 

template<typename T> 
template<bool b> 
bool checkStaleImp(T const* ptr, boost::integral_constant<bool, b> const &){ 
    return true; 
} 

template<typename T> 
bool checkStaleImp(T const* ptr, boost::true_type const&){ 
    const int oldest = 42; 
    return (42 <= ptr->getT()); 
} 

這是一個功能的三個功能。是否有更簡單的方法來完成此操作,例如使用boost::is_base_of或某物。類似於if條件或boost :: enable,如果將函數輸出轉換爲不是從Timed派生的類的常量類型。不幸的是,解決方案具有虛擬功能。

+2

你爲什麼使用模板? – AJG85 2012-02-07 16:36:15

+0

@ AJG85:實際的功能是類模板的成員(省略了縮寫的例子)所以模板的問題與否已經過時,但是閱讀fernandes的答案我認爲一個更簡單的解決方案是可能的 – Martin 2012-02-07 18:33:43

+0

這是評論。讓你考慮像重載等替代方案。 – AJG85 2012-02-07 18:41:31

回答

5

你可以做同樣的事情有兩個簡單的過載和無模板機械:

bool checkStale(void const* ptr){ 
    return true; 
} 

bool checkStale(Timed const* ptr){ 
    const int oldest = 42; 
    return (oldest <= ptr->getT()); 
} 

不需要在is_base_of上進行標籤調度。

+0

+1。對於'Timed',他也可以有一個完全專業化的模板函數來達到類似的效果。 – AJG85 2012-02-07 16:51:37

+0

我認爲這是行不通的。派生類Timed將實例化函數模板,而不是用參數'Timed const *'調用重載。 – Nawaz 2012-02-07 16:54:09

+0

@Nawaz好點。我應該只是拿出所有的模板:S – 2012-02-07 17:06:46

3

我不認爲這是相當醜陋解決方案,如你所說。但是,可以減少輔助函數的範圍,如果你實現這些本地類的靜態成員爲:

template<typename T> 
bool checkStale(T const* ptr) const 
{ 
    struct local 
    { 
     static bool checkStaleImp(T const* ptr, boost::false_type const &) 
     { 
     return true; 
     } 
     static bool checkStaleImp(T const* ptr, boost::true_type const&) 
     { 
     const int oldest = 42; 
     return (42 <= ptr->getT()); 
     } 
    }; 
    return local::checkStaleImp(ptr, boost::is_base_of<Timed, T>()); 
} 

現在,有一個功能暴露給用戶,和本地類中的實際執行情況。

順便說一下,在C++ 11中,您可以使用std::is_base_of而不是boost的版本。與std::true_typestd::false_type相同。

+1

謝謝你用我的答案指出這個問題,而不是提高它。有+1。 – 2012-02-07 17:02:17

+1

有趣的方法和整潔。如果我沒有弄錯你的代碼錯過了靜態。對於我來說,曝光並不是一個問題,因爲所有三個功能都是私人類成員(爲了簡單起見而省略),但爲了簡單起見,仍然有趣的是 – Martin 2012-02-07 18:36:21

0

使用enable_if來選擇可能的過載。由於在下面的例子中使用的條件是免費的,總是會有正好提供一個過載,因此不會產生歧義

template<typename T> 
typename std::enable_if<std::is_base_of<Timed,T>::value,bool>::type 
checkStale(T const *ptr) const { 
    const int oldest = 42; 
    return oldest <= ptr->getT(); 
} 

template<typename T> 
typename std::enable_if<!std::is_base_of<Timed,T>::value,bool>::type 
checkStale(T const *ptr) const { 
    return true; 
} 
相關問題