[英]Changing template type of a variable at runtime
我在编写 state 机器时遇到问题,该机器将在执行期间切换基于模板的变量。 目前,实现如下:
template <typename TemplateT>
class InnerClass {
void foo();
}
class StateMachine {
public:
std::unique_ptr<InnerClass<ParticularType>> inner;
void someMethod() {
...
inner->foo();
...
}
}
我需要概括这个实现,以便StateMachine
有一个成员,可以将inner
变量更改为不同的基于模板的类型:
void StateMachine::changeState(int state) {
switch(state) {
case 0:
inner.reset(new InnerClass<ParticularType0>());
break;
case 1:
inner.reset(new InnerClass<ParticularType1>());
break;
case 2:
inner.reset(new InnerClass<ParticularType2>());
break;
...
default:
assert();
}
}
我知道只有在编译时知道类型时才能使用模板,因此,很可能应该有另一种我不知道的方法。 您能否指出一些可以在这里应用的想法? 除了使用创建InnerClass
的无模板接口之外,还有其他方法吗:
class InnerClassInterface {
virtual void foo() = 0;
}
template <typename TemplateT>
class InnerClass : InnerClassInterface {
virtual void foo() override;
}
因此,很可能应该有另一种我不知道的方法
不幸的是,没有。 就像您说的那样,模板是在编译时评估的。 这意味着除非您键入所有可能的InnerClass
类型参数,就像您在 switch 语句中所做的那样,否则编译器将无法知道要实例化InnerClass
模板的哪些实例。
您最好完全改变您的设计并使用某种形式的多态性。
但如果你真的想保留这种设计,一种解决方案可能是将不同版本的ParticularType
放入专门的 class 模板中。 我已将ParticularType
重命名为State
并将其不同版本更改为一些 state 名称,因为我假设ParticularType
是为了代表状态。
// states.h
enum
{
STATE_WALKING,
STATE_RUNNING,
STATE_SHOOTING
...
};
// state.h
class StateBase
{
public:
// Insert what your states actually do here
// |
// V
virtual void someStateFunc() = 0;
};
template<int I>
class State
{
};
template<>
class State<STATE_WALKING> : public StateBase
{
public:
// Code for walking state
void someStateFunc() override
{
...
}
};
template<>
class State<STATE_RUNNING> : public StateBase
{
public:
//Code for running state
void someStateFunc() override
{
...
}
};
template<>
class State<STATE_SHOOTING> : public StateBase
{
// Code for shooting state
...
};
...
在您的示例代码中,您将inner
声明为std::unique_ptr<InnerClass<ParticularType>>
类型。 这将无法编译,因为您尝试将类型为InnerClass<ParticularType0>
和InnerClass<ParticularType1>
的unique_ptr
分配给inner
changeState
。 不过,这很容易解决,您只需要一个基础InnerState
即可继承 InnerState。
下面是InnerClass
和StateMachine
的样子:
class InnerClassBase
{
public:
virtual void foo() = 0;
...
};
template<typename T>
class InnerClass : public InnerClassBase
{
public:
void foo() override
{
...
}
};
class StateMachine {
public:
std::unique_ptr<InnerClassBase> inner;
void someMethod() {
...
inner->foo();
...
}
template<int S>
void changeState() {
inner.reset(new InnerClass<State<S>>());
}
};
并这样称呼它:
#include "states.h"
...
if(some_condition)
{
stateMachine.changeState<STATE_SHOOTING>();
}
...
每次您想添加新的 state 时,只需向State
添加新的专业化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.