我正在与同事讨论模板问题,而我们讨论的一件事就是如下所示,如果通过使用模板获得switch语句,你将如何逃脱? / p>
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 :(得分: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()
{
}