如何使用模板函数设置不同类型的值?

时间:2012-09-26 16:16:21

标签: c++ function templates

大家好!

我有一个名为UpdateValue的模板函数,它用于更新一些不同类型的值,如integer,BOOL,string等。请参阅以下代码段供您参考:

#include <typeinfo.h>

template<class T> 
void UpdateValue(T Value)
{   
    if ( typeid(int) == typeid(Value) ) 
    {  
       ZOrder(Value);
    }
    else if ( typeid(bool) == typeid(Value) )
    {  
       BOOL bShow = Value ? TRUE : FALSE;
       Show(bShow);
    }
    else if ( typeid(CString) == typeid(Value) )
    {  
       Theme(Value);
    }
}

void Show(BOOL bShow) { m_bShow = bShow; }
void ZOrder(int nZOrder) { m_nZOrder = nZOrder; }
void Theme(CString strTheme) { m_strTheme = strTheme; }

BOOL m_bShow;
int m_nZOrder;
CString m_strTheme;

但是当我使用以下语句来调用这种模板函数时

CString strValue = _T("Animal");
UpdateValue<CString>(strValue);

上述代码未能通过抛出以下异常进行编译:

  

e:\ dynaprop \ dynaprop \ mainfrm.cpp(269):错误C2664:'CMainFrame :: ZOrder':无法将参数1从'CString'转换为'int'   1 GT;没有可用于执行此转换的用户定义转换运算符,或者无法调用运算符   1 GT; e:\ dynaprop \ dynaprop \ mainfrm.cpp(67):参见函数模板实例化'void CMainFrame :: UpdateValue(T)'被编译   1 GT;同   1 GT; [   1 GT; T = CString的   1 GT; ]

请您告诉我如何解决这个问题?提前谢谢!

5 个答案:

答案 0 :(得分:1)

您实际上并没有使用模板工具。或者更确切地说错过使用它如果ZOrder(Value)获得void UpdateValue(T Value)实例化,T每次出现的CString都会被您指定的void UpdateValue(CString Value) { if ( typeid(int) == typeid(Value) ) { ZOrder(Value); } else if ( typeid(bool) == typeid(Value) ) { BOOL bShow = Value ? TRUE : FALSE; Show(bShow); } else if ( typeid(CString) == typeid(Value) ) { Theme(Value); } } 替换,会发生什么情况。但就是这样。

该功能看起来像这样

ZOrder(Value);

在模板立即生效后,正常的编译内容会发生......并且您会收到错误,因为它是value CString UpdateValue类型的template<> // specialization when T is get to be int void UpdateValue<int>(int Value) { ZOrder(Value);}; template<> // specialization when T is get to be CString void UpdateValue<bool>(bool Value) { BOOL bShow = Value ? TRUE : FALSE; Show(bShow);}; template<> // specialization when T is get to be CString void UpdateValue<CString>(CString Value) { Theme(Value);}; template<class T> //general case void UpdateValue(T Value) { cout << "IMPLEMENT ME\n";}; 。这将产生错误,即使使用RTTI,在这种情况下也不应该达到此调用路径。

您应该使用专业化来处理不同类型。尝试使用以下内容替换UpdateValue< T >的原始定义:

//Value is int
void UpdateValue(int Value) { ZOrder(Value);};
//Value is bool
void UpdateValue(bool Value) { BOOL bShow = Value ? TRUE : FALSE; Show(bShow);};
//Value is CString
void UpdateValue(CString Value){ Theme(Value);};

然后,当您调用{{1}}时,您调用具有适当正文的版本。你也不必使用RTTI。

更新:在评论者的建议之后。如果你不需要/想要处理一般情况(即未知类型),你可以诉诸普通的重载并使用:

{{1}}

然后甚至不需要模板!

答案 1 :(得分:0)

如某些其他答案中所述(或暗示),您需要将三个代码分支分成三个模板特化 - 每个参数类型一个。但这很愚蠢;如果你真的想要一个UpdateValue函数根据参数类型做三个不同的事情,那么只需编写UpdateValue的三个重载并且根本不使用模板!

(这可能无法使用BOOL类型,因为它可能也是int。您最有可能使用bool,除非有一些非常强大 - 并且奇怪 - 不这样做的原因。)

答案 2 :(得分:0)

你可以使用函数重载来实现我想要做的事情,我想, (我将其更改为使用STL字符串,以便我可以编译):

#include <typeinfo>
#include <string>

using namespace std;

bool m_bShow;
int m_nZOrder;
string m_strTheme;

void Show(bool bShow) { m_bShow = bShow; }
void ZOrder(int nZOrder) { m_nZOrder = nZOrder; }
void Theme(string strTheme) { m_strTheme = strTheme; }

void DoUpdate( bool bShow )
{
    Show( bShow );
}

void DoUpdate( int nZOrder )
{
    ZOrder( nZOrder );
}

void DoUpdate( string strTheme )
{
    Theme( strTheme );
}

template<class T>
void UpdateValue(T Value)
{
    DoUpdate( Value );
}

int main( int argc, char **argv )
{
    string strValue = "Animal";
    UpdateValue<string>(strValue);

    return 0;
}

答案 3 :(得分:0)

如前所述,UpdateValue<CString>(CString)实例化失败,因为它无法编译ZOrder(CString)表达式。请记住,模板实例化只是编译时类型替换,而不是运行时。混合运行时RTTI和模板并不是一个好主意,看起来像模板滥用。

建议使用函数重载而不是模板,它会产生相同的结果:

void UpdateValue(int Value)
{
    ZOrder(Value);
}     

void UpdateValue(bool Value)
{
   BOOL bShow = Value ? TRUE : FALSE;        
   Show(bShow);     
}

void UpdateValue(const CString& Value)
{
   Theme(Value);
} 

答案 4 :(得分:0)

代码仍在编译中,即使它是死代码。所以在哪里说:

if ( typeid(int) == typeid(Value) )
{  
   ZOrder(Value);
}

它仍然会尝试编译代码,即使它永远不会执行,因此它会抛出错误。

最好使用模板专业化:

template<class T> 
void UpdateValue(T Value) {
    // By default, do nothing.
}

void UpdateValue < int >(int value) {
    ZOrder(value);
}

void UpdateValue < bool >(bool value) {
    BOOL bShow = Value ? TRUE : FALSE;
    Show(bShow);
}

void UpdateValue < CString >(CString value) {
    Theme(value);
}

这是一个不必要的模板使用,全部告诉。你最好使用几个重载。