2016-05-15 318 views
1

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

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*>(); 
}}}} 

然后我把它从test.ino:

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

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

void loop() 
{ 
    Scheduler::update; 
} 

错误消息:

[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.] 

回答

2

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

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

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

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

+0

谢谢@ md5i。我应用你的修复程序,但我仍然有一些错误。 (我更新了问题中的错误信息) – Nugraha

+1

@Nugraha问题是你仍然在构造函数中调用'this-> callback = callback'。你不需要这个,因为它正在成员初始化列表中设置。 lambda不是可复制分配的。 – md5i

+0

看到这种问题的实际答案是非常令人愉快的,而不是通常的为什么你不使用boost ::或std :: something。 –