簡體   English   中英

在運行時更改變量的模板類型

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

下面是InnerClassStateMachine的樣子:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM