1

I am writing my own timer in c++. I was wondering whether it is possible to pass a function to the timer constructor and call this function later.

I was thinking about using function pointers for this, however I can't find a solution for passing a non-static function inside the class itself.

G++ gives me this error:

Server.cpp:61:54: error: invalid use of non-static member function serverTimer = new timer::Timer(onTimerTick,3000);

My class Server.cpp looks like this:

    private:
    void onTimerTick(){
          //do something with class variables, so can't use static? :(
      }
      public:
      Server(int port) : socket(port)
      {
          serverTimer = new timer::Timer(onTimerTick,1000);
          serverTimer->start();
      }

This is timer.h:

#ifndef TIMER_H
#define TIMER_H
namespace timer {
    class Timer{
    public:
        Timer(void (*f) (void),int interval);
        std::thread* start();
        void stop();
    private:
        int interval;
        bool running;
        void (*f) (void);
    };
}
#endif

This is timer.cpp:

#include <thread>
#include <chrono>
#include "timer.h"

timer::Timer::Timer(void (*f) (void),int interval){
    this->f = f;
    this->interval = interval;
}

std::thread* timer::Timer::start(){
    this->running = true;
    return new std::thread([this]()
    {
        while(this->running){
            this->f();
            std::this_thread::sleep_for(std::chrono::milliseconds(this->interval));
        }
    });
    //return
}

void timer::Timer::stop(){
    this->running = false;
}

Is there a better solution for this problem, or is this the wrong syntax for passing my function? Hope someone has a great solution for this.

6
  • Look up std::function. Commented Mar 7, 2016 at 22:12
  • What you kind of need are delegates. Just search stack overflow for c++ and delegates and you will find thousands of pages ;) Commented Mar 7, 2016 at 22:14
  • @BitTickler, delegate is a terrible word, which comes from language where pointer is banned, so that plain 'function pointer' can not be used. Commented Mar 7, 2016 at 22:20
  • Note that you should use std::atomic<bool> running and returning std::thread* is suspicious too. Commented Mar 7, 2016 at 22:21
  • @SergeyA Language is a funny thing, is it not? The term delegate in the context of C++ has special meaning. And there is more to it than just "function pointer". So, if it is used in other context with other meanings applies not much to how it is used in the context of c++. Commented Mar 7, 2016 at 22:22

1 Answer 1

3

The problem is that you specified a function pointer for a standalone function, but you are trying to bind it to a member function. (non-static) member functions really are different: they have a hidden this pointer that needs to be passed to them.

To solve this, one solution is to use std::function instead of a function pointer, and then pass the necessary code as a lambda.

So your function pointer becomes:

std::function<void (void)>;

and you could call it like this:

serverTimer = new timer::Timer([this]{onTimerTick ();},1000);
Sign up to request clarification or add additional context in comments.

3 Comments

That was fast! And it works :) the lambda is [this]{onTimerTick();}
I personnaly prefer std::bind in simple cases.
Note: when you have a class that has a std::function object which embeds a this pointer to itself, it is a good idea to make that class non copyable, as the copy semantics are incorrect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.