I'm trying to generate a periodic timer class using the boost.asio library. However, I get "invalid use of non-static member function" errors. The cpp file is as the following:
#include "TimerBoost.h"
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <chrono>
#include <string>
using namespace std;
boost::asio::io_context io;
TimerBoost::TimerBoost(int timerSec)
{
setParam(timerSec); //timerSec is the desired period of the timer in terms of second
boost::asio::steady_timer tim{io, std::chrono::seconds{tSec}};
tim.async_wait(boost::bind(print, &tim, &tSec));
io.run();
}
TimerBoost::TimerBoost()
{
setParam(5);
boost::asio::steady_timer tim{io, std::chrono::seconds{tSec}};
tim.async_wait(boost::bind(print, &tim, &tSec));
io.run();
}
void TimerBoost::setParam(int timerSec)
{
tSec=timerSec;
}
void TimerBoost::print(boost::asio::steady_timer* tim, int* tSec)
{
tim->expires_from_now(boost::asio::chrono::seconds(*tSec));
tim->async_wait(boost::bind(print, tim, tSec));
}
The header file is as the following:
#include <string>
#include <boost/asio/io_context.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <chrono>
#include <iostream>
#ifndef TIMERBOOST_H_
#define TIMERBOOST_H_
using namespace std;
class TimerBoost {
public:
TimerBoost(int tSec);
TimerBoost();
void setParam(int tSec);
void print(boost::asio::steady_timer* tim, int* tSec);
private:
int tSec;
};
#endif /* TIMERBOOST_H_ */
When I build the project, I get 3 errors which are:
error: invalid use of non-static member function
tim.async_wait(boost::bind(print, &tim, &tSec));
error: invalid use of non-static member function
tim.async_wait(boost::bind(print, &tim, &tSec));
error: invalid use of non-static member function
tim->async_wait(boost::bind(print, tim, tSec));
Do you know the solution of the errors? Thanks!
You have two problems:
The first is that non-static member function needs an object to be called on. This is usually passed as a hidden first argument. You solve this by passing this
as the first argument to the member-function you want to call.
The second problem is that you need to use explicit pointers to member functions. This is done by fully scoping it and using the address-of operator &
.
So the working bind
call should look something like:
boost::bind(&TimerBoost::print, this, &tim, &tSec)
Another possible solution, that is usually preferred over "binding", is to use lambdas:
tim.async_wait([tim, tSec, this]()
{
print(&tim, &tSec);
});