如何使用模板函数设置不同类型的值
How to use template function to set values with different types?
大家好!
我有一个名为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:\dynprop\dynprop\mainfrm.cpp(269):错误C2664:"CMainFrame::ZOrder":无法将参数1从"CString"转换为"int"1> 没有用户定义的可执行此转换的转换运算符,或者无法调用该运算符1> e:\dynprop\dynprop\mainfrm.cpp(67):请参阅对正在编译的函数模板实例化"void CMainFrame::UpdateValue(T)"的引用1> 与1>[1> T=C字符串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
类型。这将产生错误,即使在这种情况下使用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 MEn";};
然后,当您调用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);};
甚至不需要模板!
正如其他答案中所述(或暗示)的那样,您需要将三个代码分支分离为三个模板专门化-每个参数类型一个。但这将是愚蠢的;如果你真的想有一个UpdateValue
函数,根据参数类型做三件不同的事情,只需编写UpdateValue
的三个重载,并且根本不使用模板!
(使用BOOL
类型可能不起作用,因为它可能也是int
。你很可能应该使用bool
,除非有一些非常强烈和奇怪的理由。)
你可以使用函数重载来实现你想要做的事情,我认为,(我把它改为使用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;
}
即使是死代码,代码仍在编译中。所以你说:
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);
}
总之,这是对模板的不必要使用。你最好使用几个重载。
如前所述,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);
}
- 我收到同义重复编译器错误。我应该如何修复"类型"X"的参数与类型"X"的参数不兼容?
- C++(和 ROS) - 包含与前向声明引用,设置默认值和类型定义
- std::ifstream 在读取文件中最后一项时设置 eofbit,但仅在读取数值类型时发生
- Poco 库 PUT 方法未按预期工作,尽管主机、方法、内容类型设置正确
- 无法在 HEVC 解码器上设置输出类型 IMFTransform
- Visual Studio 2019 - 设置文件类型的默认扩展名
- 无法在VSCode中设置C++调试;无法识别调试类型
- 在 c++ 中将对象设置为等于同一类的构造函数是否有效?
- 为自定义路径类型设置提升property_tree
- C++:无法在按位函数后将 int 类型设置为非标量
- 为什么我不能为位于基类中的类中的类型设置别名
- 可以将枚举的默认类型设置为无符号字符
- 有没有办法使用显式实例化按类型设置成员变量
- C++中用于将默认变量类型设置为int的任何选项
- 是否可以继承模板类并将类型设置为当前尝试从中继承的类的模板化子类?
- 如何使用 std::conditional 根据模板参数类型设置类型
- 事件类型设置为SDL_MOUSEBUTTONDOWN,即使在未按下任何按钮时也是如此
- std::使用自定义类型设置差异
- 为具有多重继承的一个类型设置默认构造函数
- 如何为特定的模板数据类型设置条件