'How to call a function at periodic interval that takes in an object as argument in C++?

I want to execute a function at periodic interval that takes an object as argument.

I tried this answer: https://stackoverflow.com/a/72226772/13798537 that calls a function at periodic interval which takes an integer as argument, but I couldn't figure out how to call a function at periodic interval that takes an object as argument.

#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <memory>
#include <atomic>

#include "window.h" // Contains the declaration of Window class

using cancel_token_t = std::atomic_bool;

template<typename Fnc>
void set_interval(Fnc fun, std::chrono::steady_clock::duration interval,
                  std::shared_ptr<cancel_token_t> cancel_token=nullptr)
{
  std::thread([fun=std::move(fun), interval, tok=std::move(cancel_token)]()
  { 
    while (!tok || !*tok) // Call until token becomes true (if it is set)
    { 
      auto next = std::chrono::steady_clock::now() + interval;
      fun();
      std::this_thread::sleep_until(next);
    }
  }).detach();
}

void foo(Window &window)
{
  // Do something with the window object
}

int main()
{
    Window window;

    using namespace std::chrono_literals;
    auto cancel = std::make_shared<cancel_token_t>(false);
    // Ordinary rules for lambda capture apply so be careful 
    // about lifetime if captured by reference.
    set_interval([window]
                    {
                        foo(window);
                    }, 1000ms, cancel);
    //set_interval([window]{foo(window);}, 1000ms); // Without token, runs until main exits.
    std::this_thread::sleep_for(3s);
    *cancel = true;
}

I get the following error when I compile:

'void foo(Window &)': cannot convert argument 1 from 'const Window' to 'Window &'

How can I achieve this?
Thanks.



Solution 1:[1]

operator() of non-mutable lambda is const. As you capture by copy, you cannot then mutate your captured "member".

You probably want to capture by reference instead:

set_interval([&window] { foo(window); }, 1000ms, cancel);

or if you really want copy, make the lambda mutable:

set_interval([window] mutable { foo(window); }, 1000ms, cancel);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1