You actually can get pretty close to the javascript syntax:
#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <memory>
#include <atomic>
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(int n)
{
  std::cout << "Hello from foo("<<n<<")!\n";
}
int main()
{
using namespace std::chrono_literals;
  auto cancel = std::make_shared<cancel_token_t>(false);
  int x = 2;
  // Ordinary rules for lambda capture apply so be careful 
  // about lifetime if captured by reference.
  set_interval([x]{foo(5+x);}, 1000ms, cancel);
  //set_interval([x]{foo(5+x);}, 1000ms); // Without token, runs until main exits.
  std::this_thread::sleep_for(3s);
  *cancel=true;
}
I've modified the linked question and added a cancellation token which cooperatively cancels the thread when set to true. There is of course some delay between *cancel=true and the loop check.
I made the token optional, if not used, the thread will die when process exits after return from main. Although this is not guaranteed by C++, it works on common platforms.
std::chrono enforces correct usage of time units.
Feel free to ask if I should explain anything.