Hi I’m trying to make a FSM Finite State Machine in c++ with pointers and templates. I want to simplify my code and get access to the variable of the State controller inheritted or the Game Screen inside the state by using: this->_stateController->name_variable
EDIT : I simplified the code, sorry for the inconvenience, and only put the code with errors and add the compiler errors, thanks guys it will be easier to understand like that
EDIT#2 : added GameStates.cpp, State.hpp and StateController.cpp, i do intend to declare with GameScreen<GameScreenStateA> gameScreen
so i can have different initial behavior for other entities. For the GameScreen is not a template error, when i set GameScreen as a template, i don’t find how to initialize StateController because i have only set the constructor and the TransitionTo as template functions and it gets me errors, and when i put it as a class template too.
To simplify the code i thought to change my GameScreen code and my state code to something like that and create a StateController class inherited.
main.cpp
#include <iostream>
#include "GameScreen.hpp"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
GameScreen<GameScreenStateA> gameScreen;
extern std::string txt;
std::cin >> txt;
while (true and txt[0] != 'q')
{
gameScreen.Update();
gameScreen.Draw();
std::cin >> txt;
}
return 0;
}
GameScreen.hpp
#pragma once
#include "StateController.hpp"
#include "GameStates.hpp"
class GameScreen : public StateController
{
public:
std::string textGameScreen = "null";
};
GameStates.hpp
#pragma once
#include <iostream>
#include "GameScreen.hpp"
class GameScreenState : public State
{
protected:
GameScreen* _stateController = nullptr;
public:
GameScreenState(GameScreen* stateController){_stateController = stateController;};
virtual void UpdateState() = 0;
void DrawState() override;
};
class GameScreenStateA : public GameScreenState
{
public:
using GameScreenState::GameScreenState;
void Init();
void UpdateState() override;
};
class GameScreenStateB : public GameScreenState
{
public:
using GameScreenState::GameScreenState;
void Init();
void UpdateState() override;
};
GameStates.cpp
#include "GameStates.hpp"
std::string txt;
void GameScreenState::DrawState()
{
std::cout<< this->_stateController->textGameScreen <<std::endl;
}
void GameScreenStateA::Init()
{
this->_stateController->textGameScreen = "Congrats! You are in State A";
}
void GameScreenStateA::UpdateState()
{
if (txt[0]='b')
{
this->_stateController->TransitionTo<GameScreenStateB>();
}
}
void GameScreenStateB::Init()
{
this->_stateController->textGameScreen = "Congrats! You are in State B";
}
void GameScreenStateB::UpdateState()
{
if (txt[0]='a')
{
this->_stateController->TransitionTo<GameScreenStateA>();
}
}
StateController.hpp
#pragma once
#include "State.hpp"
class State;
class StateController
{
protected:
State* currentState = nullptr;
void Init();
void End();
public:
template <typename T>
StateController()
{
currentState = new T(this);
this->Init();
}
~StateController();
void Update();
void Draw();
template <typename T>
void TransitionTo();
};
template <typename T>
void StateController::TransitionTo()
{
if (currentState!=nullptr)
{
this->End();
}
currentState = new T(this);
this->Init();
};
StateController.cpp
#include "StateController.hpp"
void StateController::Init()
{
currentState->Init();
};
void StateController::End()
{
currentState->End();
delete currentState;
};
StateController::~StateController()
{
End();
};
void StateController::Update()
{
currentState->UpdateState();
};
void StateController::Draw()
{
currentState->DrawState();
};
State.hpp
#pragma once
class StateController;
class State
{
public:
virtual void Init(){};
virtual void UpdateState() = 0;
virtual void DrawState() = 0;
virtual void End(){};
};
Errors :
In file included from src/GameScreen.hpp:2,
from src/GameStates.hpp:3,
from src/GameStates.cpp:1:
src/StateController.hpp: In instantiation of 'void StateController::TransitionTo() [with T = GameScreenStateB]':
src/GameStates.cpp:19:63: required from here
src/StateController.hpp:41:20: error: invalid conversion from 'StateController*' to 'GameScreen*' [-fpermissive]
41 | currentState = new T(this);
| ^~~~~~~~~~~
| |
| StateController*
src/GameStates.hpp:27:28: note: initializing argument 1 of 'GameScreenStateB::GameScreenStateB(GameScreen*) [inherited from GameScreenState]'
27 | using GameScreenState::GameScreenState;
| ^~~~~~~~~~~~~~~
src/StateController.hpp: In instantiation of 'void StateController::TransitionTo() [with T = GameScreenStateA]':
src/GameStates.cpp:32:63: required from here
src/StateController.hpp:41:20: error: invalid conversion from 'StateController*' to 'GameScreen*' [-fpermissive]
41 | currentState = new T(this);
| ^~~~~~~~~~~
| |
| StateController*
src/GameStates.hpp:19:28: note: initializing argument 1 of 'GameScreenStateA::GameScreenStateA(GameScreen*) [inherited from GameScreenState]'
19 | using GameScreenState::GameScreenState;
| ^~~~~~~~~~~~~~~
cc1plus.exe: note: unrecognized command-line option '-Wno-writable-strings' may have been intended to silence earlier diagnostics
In file included from src/GameScreen.hpp:3,
from src/main.cpp:2:
src/GameStates.hpp:9:5: error: 'GameScreen' does not name a type; did you mean 'GameScreenState'?
9 | GameScreen* _stateController = nullptr;
| ^~~~~~~~~~
| GameScreenState
src/GameStates.hpp:11:31: error: expected ')' before '*' token
11 | GameScreenState(GameScreen* stateController){_stateController = stateController;};
| ~ ^
| )
src/main.cpp: In function 'int main()':
src/main.cpp:10:5: error: 'GameScreen' is not a template
10 | GameScreen<GameScreenStateA> gameScreen;
| ^~~~~~~~~~
src/main.cpp:10:34: error: use of deleted function 'GameScreen::GameScreen()'
10 | GameScreen<GameScreenStateA> gameScreen;
| ^~~~~~~~~~
src/GameScreen.hpp:5:7: note: 'GameScreen::GameScreen()' is implicitly deleted because the default definition would be ill-formed:
5 | class GameScreen : public StateController
| ^~~~~~~~~~
src/GameScreen.hpp:5:7: error: no matching function for call to 'StateController::StateController()'
In file included from src/GameScreen.hpp:2:
src/StateController.hpp:17:5: note: candidate: 'template<class T> StateController::StateController()'
17 | StateController()
| ^~~~~~~~~~~~~~~
src/StateController.hpp:17:5: note: template argument deduction/substitution failed:
src/GameScreen.hpp:5:7: note: couldn't deduce template parameter 'T'
5 | class GameScreen : public StateController
| ^~~~~~~~~~
src/StateController.hpp:7:7: note: candidate: 'constexpr StateController::StateController(const StateController&
'
7 | class StateController
| ^~~~~~~~~~~~~~~
src/StateController.hpp:7:7: note: candidate expects 1 argument, 0 provided
At global scope:
cc1plus.exe: note: unrecognized command-line option '-Wno-writable-strings' may have been intended to silence earlier diagnostics
13