0

每个人!

我有一个名为 UpdateValue 的模板函数,它旨在更新一些具有不同类型的值,例如整数、BOOL、字符串等。请参阅以下代码片段以供参考:

#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> 没有可以执行此操作的用户定义转换运算符转换,否则无法调用运算符 1> e:\dynaprop\dynaprop\mainfrm.cpp(67) :请参阅对函数模板实例化 'void CMainFrame::UpdateValue(T)' 的引用 1> 与 1> [ 1> T=CString 1> ]

你能告诉我如何弄清楚吗?先感谢您!

4

5 回答 5

1

您并没有真正使用模板工具。或者宁愿错过使用它。ZOrder(Value)发生的事情是您调用void UpdateValue(T Value)get 实例化,其中每次出现的都按照您指定的方式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);在 wherevalueCString类型中。这将产生一个错误,即使在这种情况下使用 RTTI 这个调用路径也不应该到达。

您应该做的是使用特化来处理不同的类型。尝试用这些替换原始定义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";};

然后,当您UpdateValue< T >调用具有适当正文的版本时。你也不必使用 RTTI。

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

//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);};

那时甚至不需要模板!

于 2012-09-26T16:27:52.347 回答
0

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

(这可能无法使用该BOOL类型,因为它可能int也是如此。你很可能应该使用它bool,除非有一些非常强大且奇怪的理由不这样做。)

于 2012-09-26T16:34:50.413 回答
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;
}
于 2012-09-26T16:34:53.377 回答
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);
} 
于 2012-09-26T16:37:53.970 回答
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);
}

总而言之,这是对模板的不必要使用。你最好使用几个重载来代替。

于 2012-09-26T16:56:09.067 回答