Не могу ссылаться на функцию вызова C ++ - PullRequest
0 голосов
/ 18 мая 2018

Я получил эту функцию, которая нуждается в ссылке на функцию:

template <typename Fn>
void Caller::operator()(const Fn& funct, bool*is_running, int time_sec)
{
    //Some code
    funct();

}

И я называю это так:

auto t = make_timer(DataHandler::dh().send, Data::sendPeriod);

Функция отправки находится в классе DataHandler, я использую статический экземплярdh:

static DataHandler& dh(){static DataHandler dh = DataHandler(); return dh;}

Возвращает ошибку:

error: must use '.*' or '->*' to call pointer-to-member function in 'funct (...)', e.g. '(...->* funct) (...)'

Он говорит, что требуется от main, где я его называю.

Кто-нибудь знает, в чем может быть проблема?

Минимальный, полный и проверяемый пример:

#include <iostream>

#include "timer.h"

class DataHandler{
public:
    static DataHandler& dh(){static DataHandler dh = DataHandler(); return dh;}
    DataHandler(){};
    void send(){std::cout << "send";}
};

int main()
{
    auto t = make_timer(DataHandler::dh().send, 20);

    return 0;
}

И timer.h, хотя я не знаю, как его сократить: (

#include <thread>
#include <functional>


struct Caller
{

    template<typename Fn>
    void operator()(const Fn& funct, bool*is_running, int time_sec);
};


template <typename Fn>
class Timer
{
protected:
    std::thread  timer_thread;
    bool    is_running;

public:
    Timer(Fn fn, int time_sec);
    Timer(const Timer&) = delete;
    Timer(Timer&& timer);


    void stop();

    ~Timer();
};




    template <typename Fn>
    void Caller::operator()(const Fn& funct, bool*is_running, int time_sec)
    {
        do
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(time_sec*1000));
            funct();

        } while(*is_running);

    }



    template <typename Fn>
    Timer<Fn>::Timer(Fn fn, int time_sec)
    :
    is_running(true)
    {
        Caller caller{};
        auto proc = std::bind(caller, fn, &(this->is_running), time_sec);
        std::thread tmp(proc);
        swap(this->timer_thread, tmp);
    }

    template <typename Fn>
    Timer<Fn>::Timer(Timer&& timer)
    :
    timer_thread(move(timer.timer_thread)),
    is_running(timer.is_running)
    {
    }

    template <typename Fn>
    void Timer<Fn>::stop()
    {
        if(this->is_running)
            this->is_running = false;
    }

    template <typename Fn>
    Timer<Fn>::~Timer()
    {
        //this->stop();
        timer_thread.join();
    }

template<typename Fn>
Timer<Fn> make_timer(Fn fn, int time)
{
    return Timer<Fn>{fn, time};
}

1 Ответ

0 голосов
/ 18 мая 2018

Это не то, как передавать нестатические функции-члены как обратный вызов.

Прежде всего, вам нужно использовать оператор address-of, чтобы получить указатель на функцию-член.Во-вторых, вам нужен экземпляр объекта для вызова функции, и это своего рода передается в качестве первого аргумента функции.

Есть два способа решения вашей проблемы:

  1. Используйте лямбда-выражение :

    make_timer([](){ DataHandler::dh().send(); }, 20);
    
  2. Используйте std::bind:

    make_timer(std::bind(&DataHandler::send, DataHandler::dh()), 20);
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...