0

After all typdefs are removed, I have the following declarations:

class Message {
  protected:
    Message* (*factories[N])(HardwareSerial);
    ...
}

class DebugMessage : Message {
  protected:
    Message* receive(HardwareSerial serial);
    ...
  public:
    DebugMessage(char* message);
    ...
};

Message* DebugMessage::receive(HardwareSerial serial){...}

DebugMessage::DebugMessage(char* message){
  ...
  factories[DEBUG_MESSAGE] = &DebugMessage::receive;
  ...
}

However when I attempt to compile it I get an error on the assignment stating

debugMessage.cpp: In constructor ‘DebugMessage::DebugMessage(char*)’:
debugMessage.cpp:4:28: error: cannot convert ‘Message* (DebugMessage::*)(HardwareSerial)’ to ‘Message* (*)(HardwareSerial)’ in assignment
   factories[DEBUG_MESSAGE] = &DebugMessage::receive;

2 Answers 2

3

You need to be more specific about the exact type of the function pointer you need to store in your array:

class Message {
  protected:
    Message* (DebugMessage::*factories[N])(HardwareSerial);
    ...
}

UPDATE (a bit more details)

The reason for that data type clarification is that member functions have an extra (hidden) first parameter this which the compiler has to know about when making a call to it via the function pointer.

Having said that I must point out that static member functions do not have that restriction (since they don't have the this parameter) and can be "freely mixed" with free functions in that regard

Sign up to request clarification or add additional context in comments.

1 Comment

Corrcet: pointers to free functions and pointers to member functions are different types.
1

@YePhlcK explained why you're having the problem but I don't know that the code he posted really solves the issue. I think you'll only be able to add pointers to DebugMessage member functions as factories using that. I've modified your code so it compiles and uses std::function and std::bind to get a function pointer to a member function.

#include <functional>

class HardwareSerial {};

class Message {
public:
    using Reciever = Message*(HardwareSerial);
protected:
    std::function<Reciever> factories[10];
};

class DebugMessage : Message {
protected:
    Message* receive(HardwareSerial serial);
public:
    DebugMessage(char* message);
};

Message* DebugMessage::receive(HardwareSerial serial){ return nullptr; }

DebugMessage::DebugMessage(char* message){
    factories[0] = std::bind(&DebugMessage::receive, this, std::placeholders::_1);
}

This way you can have member and non-member functions in your array as well as lambdas and function objects. You only need to use std::bind with the member functions.

1 Comment

These were both really good answers. If anyone were to find this question I would recommend them to code in this manner. That being said, I picked the other answer because it directly answered the question I had (even if it's a less correct way to code).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.