C++ lambda 作为参数。错误:使用已删除的函数

Nug*_*aha 1 c++ lambda arduino

我的调度程序类有一个方法,在它可以接受函数作为参数的地方调用。但是当我传递一个 lambda 表达式时,我得到了“错误:使用已删除的函数”错误。任何提示?

静态事件.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();
    }
};

}}}}
Run Code Online (Sandbox Code Playgroud)

事件.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))();
    }
};

}}}}
Run Code Online (Sandbox Code Playgroud)

调度程序.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*>();
}}}}
Run Code Online (Sandbox Code Playgroud)

然后我从 test.ino 调用它:

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

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

void loop()
{
    Scheduler::update;
}
Run Code Online (Sandbox Code Playgroud)

错误信息:

[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.]
Run Code Online (Sandbox Code Playgroud)

md5*_*d5i 6

您的班级StaticEvent<Callback>有一个类型为 的成员Callback。在您的程序中,类型Callback是您的 lambda 函数的类型。当StaticEvent<Callback>::StaticEvent被调用时,它必须初始化StaticEvent<Callback>::callback,这是通过调用Callback的默认构造函数来完成的。但是 lambda 函数类型没有默认构造函数。它根据定义被删除。

请记住,在执行构造函数中的代码之前,必须完全构造对象。如果需要在对象完全构造之前进行成员的初始化,则需要在成员初始化列表中进行

StaticEvent(unsigned long interval, Callback callback) : 
    interval(interval), callback(callback)
{}
Run Code Online (Sandbox Code Playgroud)

通过在成员初始化列表中分配回调,您可以避免默认构造它。相反,您通过复制构造函数进行分配。通常,在可能的情况下初始化成员初始化列表中的成员是一个好主意,因为这样可以避免将它们初始化两次,一次是默认的,一次是预期的。

  • @Nugraha 问题是您仍在构造函数中调用`this-&gt;callback = callback`。您不需要它,因为它已在成员初始化列表中设置。lambdas 不可复制赋值。 (2认同)