taces2
September 15, 2018, 9:59am
1
Hello,
I want to pass a lambda function as a parameter to another function.
It does not work with a member function
Error Message:
no matching function for call to 'Max6675Sensor::setInterval(const char [7], int, Max6675Sensor::setup()::<lambda()>)
The goal is to call Max6675Sensor::update() every 2000ms.
I can't use std::function -> "std::function' has not been declared"
thanks for your help!
class Max6675Sensor : public Component
void Max6675Sensor::setup()
{
thermocouple.begin(this->clkPin, this->csPin, this->soPin);
// does not work
// no matching function for call to 'Max6675Sensor::setInterval(const char [7], int, Max6675Sensor::setup()::<lambda()>)'
this->setInterval("update", 2000, [this]() {
this->update();
});
// works
this->setInterval("update", 2000, []() {
Serial.println("Test");
});
}
void Max6675Sensor::update()
{
this->value = this->thermocouple.readCelsius();
Logger->debug("sensor.max6675", "Neuer Wert: %f", this->value);
}
// Header
void setInterval(const std::string &name, uint32_t interval, void (*f)());
//
void Component::setInterval(const std::string &name, uint32_t interval, void (*f)())
{
int offset = 0;
if (interval != 0)
{
offset = (random(65535) % interval) / 2;
}
this->cancelInterval(name);
struct TimeFunction function { name, TimeFunction::INTERVAL, interval, millis() - interval - offset, f, false };
this->timeFunctions.push_back(function);
}
You cannot do that, the lambda is not part of a class, thus "this->" is not valid. You either need to specify the argument of "setInterval" as "void (Max6675Sensor::*f)()" or preferrable do an interface style declaration:
class Callable {
public:
virtual void TheCallable() = 0;
}
class Max6675Sensor : public Callable, ... {
void TheCallable() { .. }
}
void Component::setInterval(const std::string &name, uint32_t interval, Callable *c)
{
int offset = 0;
if (interval != 0)
{
offset = (random(65535) % interval) / 2;
}
this->cancelInterval(name);
struct TimeFunction function { name, TimeFunction::INTERVAL, interval, millis() - interval - offset, c, false };
this->timeFunctions.push_back(function);
}
and then invoke "c->TheCallable()" when the timer clicks.
taces2
September 15, 2018, 12:51pm
3
Thanks for the answer.
i am not sure if the interface ist the right solution for me. I want to be able to (theoretically) add all functions to the setTimeout function.
i have read much about std:function. Do you know a library for it?
I have this one GitHub - maniacbug/StandardCplusplus: Standard C++ for Arduino (port of uClibc++) and it is not working.
The method argument must be a member of "Max6675Sensor" in order to access other members using "this->". A lambda will never be a member of a class, so you are trying to do something that is not possible AFAICT.
taces2
September 16, 2018, 4:04am
5
I implemented the Interface solution
every component has two new functions
virtual void handleInterval();
virtual void handleTimeout();
the component is passed to the timefunction.
void Component::setInterval(const std::string &name, uint32_t interval, Component *c)
{
int offset = 0;
if (interval != 0)
{
offset = (random(65535) % interval) / 2;
}
this->cancelInterval(name);
struct TimeFunction function { name, TimeFunction::INTERVAL, interval, millis() - interval - offset, c, false };
this->timeFunctions.push_back(function);
}
void Component::loopInternal()
{
for (unsigned int i = 0; i < this->timeFunctions.size(); i++)
{
const uint32_t now = millis();
TimeFunction *tf = &this->timeFunctions[i];
if (tf->shouldRun(now))
{
if (tf->type == TimeFunction::INTERVAL)
{
tf->c->handleInterval();
}
else if (tf->type == TimeFunction::TIMEOUT)
{
tf->c->handleTimeout();
}
}
}
}