Home > Blockchain >  How can I add function to vector in this case?
How can I add function to vector in this case?

Time:03-12

I have this case, I can't figure it out.

I want to add a function in a vector of functions from an object to his child like this:

Child:

std::vector<void (*)(STATE oldState, STATE newState)> stateChangeHandlers;

void Digital_Output::addOnStateChangeHandler(void (*function)(STATE oldState, STATE newState)) {
    this->stateChangeHandlers.push_back(function);
}

Parent / Owner

Digital_Outputs::Digital_Outputs(json outputsConf) { //nlohmann::json

    int idx = 0;
    for (auto output: outputsConf) {
      Digital_Output *DO = new Digital_Output(output["pin"].get<int>(), idx);
//from here
          DO->addOnStateChangeHandler([DO](STATE oldState, STATE newState) -> void*{  //note the capture
            json j;
            j["state"] = newState;
            std::string jsonStr = j.dump();
            mqtt::message_ptr pubmsg = mqtt::make_message(std::string(this->getTopicBase()   "/"   DO->getName()), &jsonStr); //note the this
          });
//to here
      this->addOutput(DO);
      std::cout << "Added Output name: " << DO->getName() << " forced: " << BoolToString(DO->isForced())  << ":" << DO->getForcedValue() << " retain: " << BoolToString(DO->isRetain())  << ": " << DO->getRetainValue() << " comment: " << DO->getComment() << std::endl;
      idx  ;
    }
}

VSCode tell me :

there is no proper conversion function from "lambda []void *(STATE oldState, STATE newState)->void *" to "void (*)(STATE oldState, STATE newState)"

Next, functions stored are executed by:

void Digital_Output::_onStateChange(STATE oldState, STATE newState) {
  for(std::vector<void (*)(STATE oldState, STATE newState)>::iterator it = std::begin(this->stateChangeHandlers); it != std::end(this->stateChangeHandlers);   it) {
    (*it)(oldState, newState);
  }
}

CodePudding user response:

Your vector holds C-style function pointers. However, a capturing lambda cannot be converted to a function pointer (which is what the error message is trying to tell you), only a non-capturing lambda can. To store capturing lambdas, you will have to use std::function instead.

Also, your lambda returns a void*, but your vector expects functions that return void instead.

Also, your lambda is trying to use this without capturing it.

Try this instead:

Child

using stateHandlerFunc = std::function<void(STATE, STATE)>;

std::vector<stateHandlerFunc> stateChangeHandlers;

void Digital_Output::addOnStateChangeHandler(stateHandlerFunc function) {
    stateChangeHandlers.push_back(function);
}

Parent / Owner

Digital_Outputs::Digital_Outputs(json outputsConf) { //nlohmann::json

    int idx = 0;
    for (auto output: outputsConf) {
        Digital_Output *DO = new Digital_Output(output["pin"].get<int>(), idx);
        DO->addOnStateChangeHandler(
            [this, DO](STATE oldState, STATE newState) {
                json j;
                j["state"] = newState;
                std::string jsonStr = j.dump();
                mqtt::message_ptr pubmsg = mqtt::make_message(std::string(this->getTopicBase()   "/"   DO->getName()), &jsonStr);
            }
        );
        addOutput(DO);
        std::cout << "Added Output name: " << DO->getName() << " forced: " << BoolToString(DO->isForced())  << ":" << DO->getForcedValue() << " retain: " << BoolToString(DO->isRetain())  << ": " << DO->getRetainValue() << " comment: " << DO->getComment() << std::endl;
        idx  ;
    }
}
void Digital_Output::_onStateChange(STATE oldState, STATE newState) {
    for(auto&& handler : stateChangeHandlers) {
        handler(oldState, newState);
    }
}
  •  Tags:  
  • c
  • Related