C ++ lambda,没有看到函数和参数?

时间:2015-06-21 16:08:40

标签: c++ multithreading c++11 lambda boost-asio

我有一些代码使用围绕std::thread的包装器类,它使用一个计时器结构(基于boost::asio),每5000毫秒调用methodToCallEachIteration()

class OurThreadWrapperClass{
    OurThreadWrapperClass(boost::asio::io_service& = generic_timer_queue_s());
};

class A {
    A() : thread1(_TimerIOService){
        thread1.setInterval(5000);
        // This sets the callback function, to be called every INTERVAL ms.
        thread1.start([this](OurThreadWrapperClass&) {
            this->methodToCallEachIteration();
        });
    }

    void callAFunctionHere(std::bitset<10> arg) {
        // ...
    }

    void methodToCallEachIteration() {
        // ...
    }

    struct TimerService {
        constexpr static const size_t num_threads{2};

        TimerService(){
            for(auto& t: _threads){
                t = std::thread([this](){
                    boost::asio::io_service::work keepalive{_ioservice};

                    callAFunctionHere(_anArgument);  // The method and arg not recognised

                    (void)keepalive;
                    _ioservice.run();
                });
            }
        }

        operator boost::asio::io_service&() {
            return _ioservice;
        }

        boost::asio::io_service _ioservice{num_threads};
        std::thread _threads[num_threads];
    };

    OurThreadWrapperClass thread1;
    TimerService _TimerIOService;
    std::bitset<10> _anArgument;
};

我遇到的问题是我想从准备线程的TimerService中调用callAFunctionHere()。我无法在TimerService中移动此函数。但是,编译器抱怨找不到callAFunctionHere()_anArgument

error: cannot call member function callAFunctionHere(std::bitset<10>) without object

error: 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = TimerService::TimerService()::__lambda19; _Args = {}]', declared using local type TimerService::TimerService()::__lambda19', is used but never defined [-fpermissive]
       thread(_Callable&& __f, _Args&&... __args)

我想我需要改变A::A()中的lambda,以便编译器能够&#34;看到&#34;方法和论点,但我不太确定如何?

2 个答案:

答案 0 :(得分:1)

与往常一样,将问题分解为MVCE:

class A {
    void callAFunctionHere() {}

    struct TimerService {
        TimerService() {
            callAFunctionHere();
        }
    };
};

int main()
{
    A a;
    A::TimerService ts;
}

http://ideone.com/lEUCvO

prog.cpp: In constructor 'A::TimerService::TimerService()':
prog.cpp:6:35: error: cannot call member function 'void A::callAFunctionHere()' without object
             callAFunctionHere();

这个特殊错误告诉您,由于名称解析,编译器可以告诉您正在尝试访问外部作用域的函数/成员(class A),但是您可以从内部(class A::TimerService)的实例的上下文中重做。

这行代码:

 callAFunctionHere(_anArgument);

写在A::TimerService::TimerService()内,因此this指针为(A::TimerService*) this,代码扩展为:

 A::callAFunctionHere(A::_anArgument);

this无法应用于其中任何一个,因为AA::TimerService之间没有直接继承或转换。

这些类是嵌套的命名目的,就像namespace一样,但它们是离散的:只是因为在TimerService内声明A不在名称范围之外连接他们的实例:它不会建立继承或转换关系

也许你想要做的是创建一个通用的TimerService类,它可以通过继承来描述可重用的功能:

#include <iostream>

struct TimerService
{
    virtual void handleTimerEvent() = 0;

    TimerService()
    {
    }

    void trigger()
    {
        handleTimerEvent();
    }
};

class A : public TimerService
{

    const char* m_name;

public:
    A(const char* name_) : TimerService(), m_name(name_) {}

    void handleTimerEvent() override
    {
        std::cout << "Handling timer event in " << m_name << '\n';
    }
};

void triggerEvent(TimerService& service)
{
    service.trigger();
}

int main()
{
    A a("A instance 'a'"), b("A instance 'b'");
    triggerEvent(b);
    triggerEvent(a);
}

http://ideone.com/92aszw

答案 1 :(得分:0)

在调用callAFunctionHere的lambda中,捕获的thisclass A::TimerService实例的class A,但您试图隐式使用{{1}的成员实例。您需要引用A类型的对象,并使用该对象的成员。

class A {
    A() : _TimerIOService(this), thread1(_TimerIOService){
        //...
    }
    //...
    struct TimerService {
        A *a_;
        constexpr static const size_t num_threads{2};

        TimerService(A *a) : a_(a) {
            //...
    //...
    TimerService _TimerIOService;
    OurThreadWrapperClass thread1;
    std::bitset<10> _anArgument;
};

请注意,_TimerIOService需要thread1之前。 现在,A::TimerService中的lambda使用a_来访问所需的成员。