Nugraha
Nugraha

Reputation: 15

C++ lambda as argument. error: use of deleted function

My scheduler class has a method called every where it can accept a function as argument. But when I pass a lambda expression, I got the "error: use of deleted function" error. any tip?

StaticEvent.h

namespace Nugraha { namespace Support { namespace Facades { namespace Scheduler {

template<class Callback>
class StaticEvent : public virtual BaseEvent
{
protected:
    Callback callback;

public:
    StaticEvent(unsigned long interval, Callback callback) : callback(callback)
    {
        this->interval = interval;
        this->callback = callback;
    }

    void executeCallback()
    {
        this->callback();
    }
};

}}}}

Event.h

namespace Nugraha { namespace Support { namespace Facades { namespace Scheduler {

template<class Callback, class ObjectType>
class Event : public virtual BaseEvent
{
protected:
    Callback callback;
    ObjectType object;

public:
    Event(unsigned long interval, Callback callback, ObjectType object)
    {
        this->interval = interval;
        this->callback = callback;
        this->object   = object;
    }

    void executeCallback()
    {
       ((this->object)->*(this->callback))();
    }
};

}}}}

Scheduler.h:

namespace Nugraha { namespace Support { namespace Facades { namespace Scheduler {
using Nugraha::Collections::Vector;
using Nugraha::Collections::Collection;

class Scheduler 
{
protected:
    static Collection<BaseEvent*>* EventCollection;

public:
    template<typename Callback>
    static void every(unsigned long interval, Callback callback, int repeatCount = -1)
    {
        EventCollection->add(new StaticEvent<Callback>(interval, callback));
    }


    template<typename Callback, typename ObjectType>
    static void every(unsigned long interval, ObjectType object, Callback callback, int repeatCount = -1)
    {
        EventCollection->add(new Event<Callback, ObjectType>(interval, callback, object));
    }

    static void update()
    {
        for(int i=0; i<EventCollection->count(); i++)
        {
            EventCollection->getMemberAt(i)->update(millis());
        }
    }
};

Collection<BaseEvent*>* Scheduler::EventCollection = new Vector<BaseEvent*>();
}}}}

Then i call it from test.ino:

#include "tests.h"
using Nugraha::Support::Facades::Scheduler::Scheduler;

void setup()
{
    Scheduler::every(2000, []() {
        Serial.println("Hello!");
    });
}

void loop()
{
    Scheduler::update;
}

Error message:

[Stino - Start building "tests"...]
[ 25%] Creating D:\Code\MicrocontrollerProjects\Stino_Build\tests\tests.ino.cpp.o...
"xtensa-lx106-elf-g++" -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-IC:\Program Files (x86)\Arduino\hardware\esp8266com\esp8266/tools/sdk/include" "-IC:\Program Files (x86)\Arduino\hardware\esp8266com\esp8266/tools/sdk/lwip/include" -c -w -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections  -DF_CPU=80000000L -DLWIP_OPEN_SRC   -DARDUINO=168 -DARDUINO_ESP8266_NODEMCU -DARDUINO_ARCH_ESP8266  -DESP8266 "-IC:\Users\Nugraha\OneDrive\Tugas Akhir Deyen\Code\Fugue\tests" "-IC:\Program Files (x86)\Arduino\hardware\esp8266com\esp8266\cores\esp8266" "-IC:\Program Files (x86)\Arduino\hardware\esp8266com\esp8266\variants\d1" "-IC:\Program Files (x86)\Arduino\hardware\esp8266com\esp8266\libraries\ESP8266WiFi\src" "-IC:\Program Files (x86)\Arduino\hardware\esp8266com\esp8266\libraries\ESP8266HTTPClient\src" "-ID:\Code\MicrocontrollerProjects\libraries\Timer" "-ID:\Code\MicrocontrollerProjects\libraries\ArduinoJson" "D:\Code\MicrocontrollerProjects\Stino_Build\tests\tests.ino.cpp" -o "D:\Code\MicrocontrollerProjects\Stino_Build\tests\tests.ino.cpp.o"
In file included from C:/Users/Nugraha/OneDrive/Tugas Akhir Deyen/Code/Fugue/tests/../vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Header/Nugraha.h:39:0,

                 from C:/Users/Nugraha/OneDrive/Tugas Akhir Deyen/Code/Fugue/tests/../vendor/nugraha/tugasAkhirWahyu/tugasAkhirWahyu.h:4,

                 from C:/Users/Nugraha/OneDrive/Tugas Akhir Deyen/Code/Fugue/tests/../vendor/vendor.h:4,

                 from C:/Users/Nugraha/OneDrive/Tugas Akhir Deyen/Code/Fugue/tests/../Fugue.h:16,

                 from C:/Users/Nugraha/OneDrive/Tugas Akhir Deyen/Code/Fugue/tests/tests.h:13,

                 from C:/Users/Nugraha/OneDrive/Tugas Akhir Deyen/Code/Fugue/tests/tests.ino:1:

C:/Users/Nugraha/OneDrive/Tugas Akhir Deyen/Code/Fugue/tests/../vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Header/../Support/Facades/Scheduler/StaticEvent.h: In instantiation of 'Nugraha::Support::Facades::Scheduler::StaticEvent<Callback>::StaticEvent(long unsigned int, Callback) [with Callback = setup()::__lambda0]':

C:/Users/Nugraha/OneDrive/Tugas Akhir Deyen/Code/Fugue/tests/../vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Header/../Support/Facades/Scheduler/Scheduler.h:22:9:   required from 'static void Nugraha::Support::Facades::Scheduler::Scheduler::every(long unsigned int, Callback, int) [with Callback = setup()::__lambda0]'

C:/Users/Nugraha/OneDrive/Tugas Akhir Deyen/Code/Fugue/tests/tests.ino:8:6:   required from here

C:/Users/Nugraha/OneDrive/Tugas Akhir Deyen/Code/Fugue/tests/../vendor/nugraha/tugasAkhirWahyu/src/Nugraha/Header/../Support/Facades/Scheduler/StaticEvent.h:13:24: error: use of deleted function 'setup()::__lambda0& setup()::__lambda0::operator=(const setup()::__lambda0&)'

         this->callback = callback;

                        ^

C:/Users/Nugraha/OneDrive/Tugas Akhir Deyen/Code/Fugue/tests/tests.ino:6:29: note: a lambda closure type has a deleted copy assignment operator

     Scheduler::every(2000, []() {

                             ^


[Stino - Exit with error code 1.]

Upvotes: 1

Views: 5142

Answers (1)

md5i
md5i

Reputation: 3083

Your class StaticEvent<Callback> has a member of type Callback. In your program, the type of Callback is the type of your lambda function. When StaticEvent<Callback>::StaticEvent is called, it has to initialize StaticEvent<Callback>::callback, which is does by calling Callback's default constructor. But lambda function types have no default constructor. It is deleted by definition.

Remember, objects have to be fully constructed before the code in the constructor can be executed. If you need to do initialization of members before the object is fully constructed, you need to do this in the member initialization list.

StaticEvent(unsigned long interval, Callback callback) : 
    interval(interval), callback(callback)
{}

By assigning callback in the member initialization list, you avoid default-constructing it. Instead, you are assigning by copy constructor. In general, it is a good idea to initialize members in the member initialization list when possible, as this avoids initializing them twice, once by default, and once as intended.

Upvotes: 6

Related Questions