[英]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.