2014-06-24 148 views
0

我正在和一位同事討論關於模板的問題,我們正在討論的一個問題是,給定一個如下所示的類,您將如何脫離開關聲明通過使用模板?如何通過模板類型參數

enum EVersion 
{ 
    Version_1, 
    Version_2, 
}; 

class CBar 
{ 
    ... 
public: 
    EVersion ver; 
}; 

class CFoo 
{ 
    void Reset() 
    { 
     switch (pBar->ver) 
     { 
      case Version_1: 
       TemplateHelperMethod<Version_1>::DoSomething(); 
      break; 

      case Version_2: 
       TemplateHelperMethod<Version_2>::DoSomething(); 
      break; 
     } 
    } 

    CBar *pBar; 
}; 

CFoo* pFoo = new CFoo(pBar); 
pFoo->Reset(); 

一種解決方案是創建一個派生模板類,和移動功能,需要使用基於版本的switch語句中派生類。

class CFoo 
{ 
    ... 
    CBar *pBar; 
}; 

template <EVersion Ver> 
class CFoo2 : public Foo 
{ 
    void Reset() 
    { 
     TemplateHelperMethod<Ver>::DoSomething(); 
    } 
}; 

CFoo2<Version_2>* pFoo = new CFoo2<Version_2>(pBar); 
pFoo->Reset(); 

然而,我的同事認爲,它可以保持在基類原有的功能,只是將其更改爲一個模板方法(類似下圖)。不過,我有點密集的如何工作。你將如何使用派生類將類型傳遞給模板方法?如果有人有任何想法,請告訴我。謝謝。

class CFoo 
{ 
    template <EVersion Ver> 
    void Reset() 
    { 
     TemplateHelperMethod<Ver>::DoSomething(); 
    } 

    CBar *pBar; 
}; 

template <EVersion Ver> 
class CFoo2 : public Foo 
{ 
    // does anything go here? 
}; 

CFoo2<Version_2>* pFoo = new CFoo2<Version_2>(pBar); 
pFoo->Reset(); 

OR 

CFoo* pFoo = new CFoo(pBar); 
// Can you do this? since CFoo2 derives from CFoo 
// and has no additional members... 
CFoo2<Version_2>* pFoo2 = static_cast<CFoo2<Version_2>*>(pFoo); 
pFoo2->Reset(); 
+0

如果發佈的代碼示例有*編譯*的機會,它會爲您的問題引發大量的氧氣。它幾乎*看起來像你試圖標籤發送,但很難說。 – WhozCraig

+0

請閱讀並嘗試一下。 http://www.cprogramming.com/tutorial/templated_functions.html –

回答

0

我認爲你的同事建議是不可能的,因爲pBar->ver不是編譯時間常數。您不能將其用作模板參數。

正確的解決辦法,以消除運行時可變開關是運行時多態性

struct Version 
{ 
    virtual ~Version() = default; 
    virtual void DoSomething() = 0; 
}; 

class CBar 
{ 
public: 
    Version& ver; 
}; 


class CFoo 
{ 
public: 
    void Reset() 
    { 
     pBar->ver.DoSomething(); 
    } 
    CBar *pBar; 
}; 

如果您CBar::ver編譯時間常數,你可以用它來就可以了專門CFoo

template<EVersion Version> 
struct CBar 
{ 
    EVersion version = Version; 
}; 


template<EVersion Version> 
struct CFoo 
{ 
    void Reset(); 
    CBar<Version> pBar; 
}; 


template<> 
void CFoo<Version_1>::Reset() 
{ 
} 

template<> 
void CFoo<Version_2>::Reset() 
{ 
}