Пересылка функции с переменным количеством аргументов в C++11

Пытаюсь написать обёртку над std::thread с флагом isNeedtoStop и циклом, постоянно вызывающим переданную функцию, пока isNeedToStop не установлен. Возникла трудность в том как правильно передать функцию и параметры в функцию цикла. Возможно ли это на С++11 в принципе?

class CThread
{
public:
     template<typename TF, typename... TArgs>
     void Start(TF&& func, TArgs&&... _args)
     {
         m_isNeedtoStop = false;
         m_thrd = std::thread(std::bind(&CThread::Loop, this, 
                                        std::forward<TF>(func), 
                                        std::forward<TArgs>(_args)...));
     }

     template<typename TF, typename... TArgs>
     void Loop(TF&& func, TArgs&&... _args)
     {
          while (!m_isNeedToStop)
          {
               func(_args...);
          }
     }

private:
    std::thread       m_thrd;
    std::atomic<bool> m_isNeedtoStop;
};

И вызов из другого объекта:

class CTest
{
public:
    void PrintHello(int a, int b, int c)
    {
        std::cout<<"Hello, concurrent world "<< a+b+c << std::endl;
    }

    void Run()
    {
         m_thread.Start(&CTest::PrintHello, this, 6, 7, 8);
    }

private:
    CThread m_thread;
};

Ответы (2 шт):

Автор решения: user7860670

Пример из С++-20, где был добавлен класс std::jthread, имеющий встроенную поддержку флага прерывания потока. При вызове деструктора он сам выставит флажек прерывания работы и дождется завершения потока:

#include <chrono>
#include <iostream>
#include <thread>

class CTest
{
    private: static void
    PrintHello_Sink(::std::stop_token token, CTest * thiz, int a, int b, int c)
    {
        return thiz->PrintHello(token, a, b, c);
    }
    
    public: void
    PrintHello(::std::stop_token token, int a, int b, int c)
    {
        while (not token.stop_requested())
        {
            ::std::cout << "Hello, concurrent world " << a+b+c << ::std::endl;
            ::std::this_thread::sleep_for(::std::chrono::seconds{1});
        }
    }

    public: void
    Run()
    {
        m_thread = ::std::jthread{&CTest::PrintHello_Sink, this, 6, 7, 8};
    }

    private: ::std::jthread m_thread;
};

int
main()
{
    CTest test{};
    test.Run();
    ::std::this_thread::sleep_for(::std::chrono::seconds{2});
    return 0;
}

online compiler

→ Ссылка
Автор решения: user7860670

Вот вариант велосипедного jthread для C++-11:

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

class StopToken
{
    private: ::std::shared_ptr<::std::atomic<bool>> m_p_flag;

    public: StopToken()
    :   m_p_flag{::std::make_shared<::std::atomic<bool>>()}
    {}

    public: StopToken(StopToken const & other)
    :   m_p_flag{other.m_p_flag}
    {}

    public: void operator =(StopToken const & other)
    {
        m_p_flag = other.m_p_flag;
    }

    public: bool stop_requested() const noexcept
    {
        return *m_p_flag;
    }

    public: void request_stop() noexcept
    {
        (*m_p_flag) = true;
    }

    public: void reset() noexcept
    {
        (*m_p_flag) = false;
    }
};

class JThread
{
    private: StopToken m_stop_token;
    private: ::std::thread m_thread;

    public: JThread()
    :   m_stop_token{}, m_thread{}
    {}

    public: ~JThread() noexcept
    {
        Try_Join();
    }

    public: template<typename x_Functor, typename... x_Args>
    JThread(x_Functor && functor, x_Args && ... args)
    :   m_stop_token{}
    ,   m_thread{::std::forward<x_Functor>(functor), m_stop_token, ::std::forward<x_Args>(args)...}
    {}

    public: JThread(JThread && other)
    :   m_stop_token{}
    ,   m_thread{::std::move(other.m_thread)}
    {
        ::std::swap(m_stop_token, other.m_stop_token);
    }

    public: void operator =(JThread && other) noexcept
    {
        if (this != &other)
        {
            Try_Join();
            m_thread = ::std::move(other.m_thread);
            ::std::swap(m_stop_token, other.m_stop_token);
        }
    }

    private: void Try_Join() noexcept
    {
        if (m_thread.joinable())
        {
            m_stop_token.request_stop();
            m_thread.join();
        }
        m_stop_token.reset();
    }
};

class CTest
{
    public: using
    Thread = ::JThread;

    public: using
    StopToken = ::StopToken;

    private: static void
    PrintHello_Sink(StopToken token, CTest * thiz, int a, int b, int c)
    {
        return thiz->PrintHello(token, a, b, c);
    }
    
    public: void
    PrintHello(StopToken token, int a, int b, int c)
    {
        while (not token.stop_requested())
        {
            ::std::cout << "Hello, concurrent world " << a+b+c << ::std::endl;
            ::std::this_thread::sleep_for(::std::chrono::seconds{1});
        }
    }

    public: void
    Run()
    {
        m_thread = Thread{&CTest::PrintHello_Sink, this, 6, 7, 8};
    }

    private: Thread m_thread;
};

int
main()
{
    CTest test{};
    test.Run();
    ::std::this_thread::sleep_for(::std::chrono::seconds{2});
    return 0;
}

online compiler

→ Ссылка