I have two questions: the first on the cause of the specific error I'm trying to solve here, the second on the validity of my approach to the problem.
I'm trying to create a state machine that uses member function pointers, and I'm lost in the details. Other Q/As on the member function pointer topic seem to deal with calling the member functions from outside the class, and advocate the use of std::function and std::bind. I also read the C++ FAQ on pointers to member functions which also gives examples of calling the member functions outside the class. I'm not entirely sure those examples apply to what I'm trying to do.
This state machine approach is general across what I'm trying to do for this embedded application (This is the first real application I've written in C++. If this approach is stupid, please help me toward a better solution.). The specific code below is for the MessageHandler class. The idea is each hardware communication port ISR will copy its contents to its own buffer, and then queue its own MessageHandler object to process. There's several communication interfaces, but the protocol is the same on all of them.
Some snippets from MessageHandler.h:
class MessageHandler
{
private:
enum state_t {
WAIT_METADATA,
WAIT_PAYLOAD,
NUM_STATES
};
enum transfer_t {
INPUT_PARTIAL_METADATA,
INPUT_METADATA,
INPUT_PARTIAL_PAYLOAD,
INPUT_COMMAND,
INPUT_TIMEOUT,
INPUT_UNKNOWN,
NUM_TRANSFER_INPUTS
};
typedef transfer_t (MessageHandler::*transferFunction)();
transferFunction transferFunctionTable[NUM_STATES] = {
checkMetadata,
checkPayload
};
typedef state_t(MessageHandler::*stateFunction)();
stateFunction stateFunctionTable[NUM_TRANSFER_INPUTS] = {
gotPartialMetadata,
gotMetadata,
gotPartialPayload,
gotCommand,
gotTimeout,
gotUnknownError
};
size_t processTable[NUM_TRANSFER_INPUTS][NUM_STATES] = {
{ 0, 5 },
{ 1, 5 },
{ 5, 2 },
{ 5, 3 },
{ 4, 4 },
{ 5, 5 }
};
...
state_t state;
transfer_t getInput();
transfer_t checkMetadata();
transfer_t checkPayload();
state_t gotPartialMetadata();
state_t gotMetadata();
state_t gotPartialPayload();
state_t gotCommand();
state_t gotTimeout();
state_t gotUnknownError();
...
public:
...
state_t process();
};
And some examples from MessageHandler.cpp:
MessageHandler::transfer_t MessageHandler::getInput()
{
...
return transferFunctionTable[state]();
}
Another from MessageHandler.cpp:
MessageHandler::state_t MessageHandler::process()
{
do {
state = stateFunctionTable[ processTable[getInput()][state] ]();
} while (cbRemaining > 0);
}
I don't understand why for the two member functions I provided I get errors with the function table calls:
Error: expression preceding parentheses of apparent call must have (pointer-to-) function type
Isn't that what I provided? That is, how are the types of transferFunctionTable and stateFunctionTable not pointers to functions?
I think to fix this I have to make all the functions static and pass references/pointers to the MessageHandler object.
Thanks in advance for your help.
MessageHandler::transfer_t MessageHandler::getInput()
{
return transferFunctionTable[state]();
}
should be
MessageHandler::transfer_t MessageHandler::getInput()
{
return (this->*transferFunctionTable[state])();
}