Как написать анонимную функцию/лямбду, которая проходит себя как обратный вызов?

Я изучаю boost::asio и C++11 одновременно. Одна из моих тестовых программ, которая на самом деле является адаптацией одного из примеров, приведенных в учебнике boost::asio, заключается в следующем:

#include 
#include 
#include 

class printer {

// Static data members
private:
    const static boost::posix_time::seconds one_second;

// Instance data members
private:
    boost::asio::deadline_timer timer;
    int count;

// Public members
public:
    printer(boost::asio::io_service& io)
        : timer(io, one_second), count(0) {

        std::function callback;
        callback = [&](const boost::system::error_code&) { // critical line
            if (count < 5) {
                std::cout << "Current count is " << count++ << std::endl;

                timer.expires_at(timer.expires_at() + one_second);
                timer.async_wait(callback);
            }
        };

        timer.async_wait(callback);
    }

    ~printer() {
        std::cout << "Final count is " << count << std::endl;
    }
};

const boost::posix_time::seconds printer::one_second(1);

int main() {
    boost::asio::io_service io;
    printer p(io);
    io.run();

    return 0;
}

Когда я запускаю эту программу, я получаю ошибку сегментации. Я понимаю, почему я получаю ошибку сегментации. После завершения работы конструктора переменная callback конструктора выходит за рамки области действия, а переменная callback конструктора, которая является ссылкой на переменную callback конструктора, становится висящей ссылкой.

Поэтому я изменяю критическую строку с:

        callback = [callback, &](const boost::system::error_code&) { // critical line

Затем компилую ее, запускаю и получаю ошибку вызова плохой функции. Снова Я понимаю, почему я получаю ошибку вызова плохой функции. В области действия лямбды переменной callback конструктора до сих пор не присвоено никакого значения, поэтому она для всех практических целей является указателем висячих функций. Следовательно, переменная callback лямбды, которая является копией переменной callback конструктора, также является указателем висячих функций.


Подумав над этой проблемой некоторое время, я понял, что мне действительно нужно, чтобы обратный вызов мог ссылаться на себя с помощью указателя функции, а не ссылки на указатель функции. В примере это было достигнуто за счет использования именоваемой функции в качестве обратного вызова вместо анонимной. Однако передача именованных функций в виде обратных вызовов не очень элегантна. Есть ли способ получить анонимную функцию, имея указатель функции на себя в качестве локальной переменной?

7
задан pyon 14 December 2011 в 05:27
поделиться