Переменные шаблоны и шаблонные классы

#c

#c

Вопрос:

Я пытаюсь создать какую-то таблицу переходов для StateMachine. Я довольно новичок в шаблонах. Поэтому, пожалуйста, простите меня, если я допустил глупую ошибку.

Это мой код для класса Transitiontable: .cpp и .h

 template<typename T, typename ...Arg>
class TransitionTable
{
public:

    TransitionTable(T first, Arg... rest);
    ~TransitionTable();
};

template <typename T, typename ... Arg>
TransitionTable<T, Arg...>::TransitionTable(T first, Arg... rest) {
    std::cout << "New Transition Table" << std::endl;
    std::unique_ptr<T> Test = new T;
    TransitionTable(rest...);
}

template <typename T, typename ... Arg>
TransitionTable<T, Arg...>::~TransitionTable() {}

  

Это мой основной ():

 int main() {

    TransitionTable
        <
        State1, State2, Event1,
        State1, State3, Event2,
        State2, State3, Event1,
        State2, State1, Event2,
        State3, State1, Event1,
        State3, State2, Event2

        > test(State1, State2, Event1,
            State1, State3, Event2,
            State2, State3, Event1,
            State2, State1, Event2,
            State3, State1, Event1,
            State3, State2, Event2);


    return 0;
}
  

Итак, я пытаюсь создать новое состояние и сразу же после этого удалить новое состояние с помощью этого уникального указателя. Это просто для того, чтобы я попытался больше понять о шаблонах переменных. Все классы состояний Con и Destruktor имеют внутри себя cout, в котором указывается, создали ли они сами себя или удалили.

Пример для класса состояний. Все они выглядят одинаково:

 public:
    State1(){
        std::cout << "State1 erstellt! " << m_Name << "n";
    }

    virtual ~State1() {
        std::cout << "State1 zerstoert! " << m_Name << "n";
    }

    void Entry() override {
        std::cout << "Entry State1!n";
    }

    void Exit() override {
        std::cout << "Exit State1!n";
    }

private:
    std::string m_Name;
};
  

Моя проблема сейчас в том, что он практически ничего не делает.. Может кто-нибудь сказать мне, пожалуйста, почему? Если я установлю точку останова в самом начале, отладчик даже не откроется.

Приветствую и благодарю за помощь!

Редактировать:

Statemachine .cpp

 

StateMachine::StateMachine(): m_InitState(m_CurrentState) {}

StateMachine::StateMachine(std::string na, trans_map trans, AbstractState* init): m_Name(na),
                                                                                  m_InitState(init),
                                                                                  m_TransitionTable(trans) {}

StateMachine::~StateMachine() = default;

void StateMachine::Start() {
    m_CurrentState = m_InitState;
    std::cout << "Zustandsmachine gestartet!n";
    m_CurrentState->Entry();
}

void StateMachine::Stop() {
    m_CurrentState->Exit();
    m_CurrentState = nullptr;
    std::cout << "Zustandsmachine gestoppt!n";
}

void StateMachine::HandleEvent(AbstractEvent* ev) {

    for(auto outer_map : m_TransitionTable) {
        if(outer_map.first == m_CurrentState) {
            if(outer_map.second.find(ev)->second)
                m_NextState = outer_map.second.find(ev)->second;
        }
    }
    if (m_CurrentState != m_NextState)
        Transition();
}


void StateMachine::Transition() {

    m_CurrentState->Exit();
    m_NextState->Entry();
    m_CurrentState = m_NextState;

}

void StateMachine::SetInitState(AbstractState* init) {
    m_InitState = init;
}

void StateMachine::CreateTransitionTable(const trans_mapamp; transition) {
    m_TransitionTable = transition;
}

AbstractState* StateMachine::GetCurrentState() const {
    return m_CurrentState;
}
  

Statemachine .h

 #pragma once
#include <map>
#include <string>
#include <iostream>
#include "AbstractState.h"
#include "AbstractEvent.h"



typedef std::map<AbstractEvent*, AbstractState* > trans_map_inner;
typedef std::map<AbstractState*, trans_map_inner> trans_map;



class StateMachine{
public:

    StateMachine();
    StateMachine(std::string na, trans_map trans, AbstractState* init);
    ~StateMachine();

    void Start();

    void Stop();

    void HandleEvent(AbstractEvent* ev);


    void Transition();

    void SetInitState(AbstractState* init);

    void CreateTransitionTable(const trans_mapamp; transition);

    AbstractState* GetCurrentState() const;
private:
    std::string m_Name;
    AbstractState* m_CurrentState = nullptr;
    AbstractState* m_NextState = nullptr;
    AbstractState* m_InitState;
    trans_map m_TransitionTable;

};
  

Классы Abstractstate и Abstactevent — это всего лишь небольшие абстрактные классы.

Комментарии:

1. c ??. Вы имеете в виду под: «Это мой код для класса Transitiontable: .cpp и .h». Поскольку это шаблонный класс, весь код должен быть доступен в callsite -> only header. Если я правильно помню, TransitionTable в теле вашего конструктора это сокращение от TransitionTable<T,Arg...> , поэтому я бы ожидал некоторого количества ошибок параметров. Но поскольку вы не упомянули что-то подобное, я, должно быть, ошибаюсь.

2. Вы уверены, что выполняете отладочную сборку? Какую IDE / компилятор вы используете?

3. Я думаю, вы правы. Я помню что-то вроде того, что все должно быть в заголовке, но это не решило мою проблему… Я использую VS 2015 Pro. Компилятор, я полагаю, g ? Но я не уверен. Да, я уверен, что запускаю отладку.

4. @HenningWilmer Нет, если вы используете, Visual Studio ваш компилятор является VC компилятором

5. @WBuck Спасибо! Полезно знать.

Ответ №1:

Проблема в том, что это

 TransitionTable
    <
    State1, State2, Event1,
    State1, State3, Event2,
    State2, State3, Event1,
    State2, State1, Event2,
    State3, State1, Event1,
    State3, State2, Event2

    > test(State1, State2, Event1,
        State1, State3, Event2,
        State2, State3, Event1,
        State2, State1, Event2,
        State3, State1, Event1,
        State3, State2, Event2);
  

не вызывает конструктор, как вы можете подумать. То, что вы написали там, является объявлением функции, которая возвращает TransitionTable<State1, State2, …> и принимает параметры типов State1, State2, … . Итак, ваш код действительно ничего не делает, кроме объявления функции и возврата 0. Это также известно как самый неприятный синтаксический анализ. Если бы вы хотели, чтобы это был вызов конструктора, вам пришлось бы создавать объекты типов State1, State2, … и предоставлять их в качестве аргументов конструктору. State1, State2, … это не список аргументов вызова функции, это список типов…

Комментарии:

1. Большое вам спасибо. Это объясняет это. Моя проблема в том, что я не хочу создавать объекты. Я только хочу создать состояние, которое в данный момент активно, и уничтожить его, если оно покинет состояние.

2. @HenningWilmer Хорошо, но тогда почему вы TransitionTable ожидаете, что в качестве аргумента будет использоваться один объект любого типа состояния?

3. Я бы сказал, потому что это неправильно. Мне нужна таблица переходов, которая принимает все классы состояний, и если мне нужно обработать событие, я хочу заглянуть в таблицу переходов и создать из нее новый объект Nextstate.

4. @HenningWilmer Ну, ваш TranstitionTable знает все типы состояний, поэтому он должен быть способен создавать объекты состояний по мере необходимости. Но для этого ему нужно будет каким-то образом знать, в каком состоянии он находится, и иметь информацию о том, из какого состояния переходить, где оно находится. Ваш вопрос, похоже, не указывает, как все это должно обрабатываться…

5. У меня есть класс Statemachine, который обрабатывает все это. И переходы находятся внутри приведенного выше кода. Итак, если появляется его пример для State1 и Event1, он переключается в State2.. Но не могли бы вы объяснить мне, как извлечь типы состояний? И как Transitiontable узнает все состояния? Я