如何在 C++ 中检查模板 class 中的类型?
How do I check types within a template class in c++?
我有一个按钮 class 可以显示图像或一行文本,我正在尝试使用模板实现。
如果是文本,则模板类型为:const char*
如果是图片,则模板类型为:const wchar_t*
这里是需要区分这两种类型的方法:
template <typename T>
void Button<T>::draw(EasyGraphics* canvas)
{
canvas->setBackColour(colour);
if (mouseOver)
{
canvas->setPenColour(EasyGraphics::BLACK, 4);
}
else
{
canvas->setPenColour(EasyGraphics::BLACK, 2);
}
canvas->drawRectangle(Entity::GetX(), Entity::GetY(), Entity::getWidth(), Entity::getHeight(), true);
canvas->setFont(20, L"");
canvas->setTextColour(textColour);
switch (typeid(T))
{
// Button has display text
case typeid(const char*):
{
canvas->drawText(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3);
break;
}
// Button has display image
case typeid(const wchar_t*):
{
canvas->drawBitmap(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3, 60, 60, 0x0000FF00);
break;
}
}
}
我似乎无法让底部的开关正常工作。我不确定切换是否是最好的方法。任何建议将不胜感激,干杯。
使用类型特征(和 if constexpr
)而不是 typeid
。例如:
void g_char(const char*);
void g_wchar_t(const wchar_t*);
template <typename T>
void f(T)
{
if constexpr (std::is_same_v<T, const char*>)
{
g_char(T());
}
else if constexpr (std::is_same_v<T, const wchar_t*>)
{
g_wchar_t(T());
}
}
http://coliru.stacked-crooked.com/a/08e9e66ed5c776a4
开关在这里不起作用的原因是条件必须可以隐式转换为整数类型,而 std::type_info
(typeid
returns)不是。
但是,如果您尝试保留 typeid
表达式,那么当您尝试调用 drawText
或 drawBitmap
时,就会遇到编译时类型检查的问题。除非您使用 constexpr 分支 (if constexpr
),否则这两个调用都必须有效。但是,条件必须是编译时常量,其中不能使用 typeid
。因此,您可以使用类型特征,特别是 std::is_same
.
进行模板专业化:
template <typename T>
void DoDraw(EasyGraphics* canvas);
template<>
void DoDraw<char>(EasyGraphics* canvas)
{
canvas->drawText(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3);
}
template<>
void DoDraw<wchar_t>(EasyGraphics* canvas)
{
canvas->drawBitmap(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3, 60, 60, 0x0000FF00);
}
template <typename T>
void Button<T>::draw(EasyGraphics* canvas)
{
...
DoDraw(canvas);
}
*检查模板参数,有 const char*
而不仅仅是 char
.
很奇怪
您可以选择 typeid,但要注意它不适合 运行 时间多态性。例如下面。
#include <iostream>
template<class T>
void getType(T A) {
std::cout<<typeid(A).name()<<"\n";
}
class Base {
};
class Derived : public Base {
};
int main(){
getType(Base());
getType(Derived());
Derived *d = new Derived();
getType(d);
Base *b = d;
getType(b);
return 0;
}
输出:
4Base
7Derived
P7Derived
P4Base
我有一个按钮 class 可以显示图像或一行文本,我正在尝试使用模板实现。
如果是文本,则模板类型为:const char*
如果是图片,则模板类型为:const wchar_t*
这里是需要区分这两种类型的方法:
template <typename T>
void Button<T>::draw(EasyGraphics* canvas)
{
canvas->setBackColour(colour);
if (mouseOver)
{
canvas->setPenColour(EasyGraphics::BLACK, 4);
}
else
{
canvas->setPenColour(EasyGraphics::BLACK, 2);
}
canvas->drawRectangle(Entity::GetX(), Entity::GetY(), Entity::getWidth(), Entity::getHeight(), true);
canvas->setFont(20, L"");
canvas->setTextColour(textColour);
switch (typeid(T))
{
// Button has display text
case typeid(const char*):
{
canvas->drawText(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3);
break;
}
// Button has display image
case typeid(const wchar_t*):
{
canvas->drawBitmap(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3, 60, 60, 0x0000FF00);
break;
}
}
}
我似乎无法让底部的开关正常工作。我不确定切换是否是最好的方法。任何建议将不胜感激,干杯。
使用类型特征(和 if constexpr
)而不是 typeid
。例如:
void g_char(const char*);
void g_wchar_t(const wchar_t*);
template <typename T>
void f(T)
{
if constexpr (std::is_same_v<T, const char*>)
{
g_char(T());
}
else if constexpr (std::is_same_v<T, const wchar_t*>)
{
g_wchar_t(T());
}
}
http://coliru.stacked-crooked.com/a/08e9e66ed5c776a4
开关在这里不起作用的原因是条件必须可以隐式转换为整数类型,而 std::type_info
(typeid
returns)不是。
但是,如果您尝试保留 typeid
表达式,那么当您尝试调用 drawText
或 drawBitmap
时,就会遇到编译时类型检查的问题。除非您使用 constexpr 分支 (if constexpr
),否则这两个调用都必须有效。但是,条件必须是编译时常量,其中不能使用 typeid
。因此,您可以使用类型特征,特别是 std::is_same
.
进行模板专业化:
template <typename T>
void DoDraw(EasyGraphics* canvas);
template<>
void DoDraw<char>(EasyGraphics* canvas)
{
canvas->drawText(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3);
}
template<>
void DoDraw<wchar_t>(EasyGraphics* canvas)
{
canvas->drawBitmap(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3, 60, 60, 0x0000FF00);
}
template <typename T>
void Button<T>::draw(EasyGraphics* canvas)
{
...
DoDraw(canvas);
}
*检查模板参数,有 const char*
而不仅仅是 char
.
您可以选择 typeid,但要注意它不适合 运行 时间多态性。例如下面。
#include <iostream>
template<class T>
void getType(T A) {
std::cout<<typeid(A).name()<<"\n";
}
class Base {
};
class Derived : public Base {
};
int main(){
getType(Base());
getType(Derived());
Derived *d = new Derived();
getType(d);
Base *b = d;
getType(b);
return 0;
}
输出:
4Base
7Derived
P7Derived
P4Base