Шаблон Variadic для расчета для параметра-члена - PullRequest
3 голосов
/ 14 октября 2019

У меня есть класс, который оборачивает std :: future. Он является результатом асинхронного вызова универсальной функции, указанной шаблоном, а аргументов - шаблоном с переменными числами.

template <class Fn, class... Args>
class AsyncTask {
public:    
    AsyncTask(const Fn& func, Args&&... args)        
        : m_fut(std::async(std::launch::async, func, std::forward<Args>(args)...)){};
    virtual ~AsyncTask(){}
private:
    std::future<typename std::result_of<Fn(Args...)>::type> m_fut;
};

Теперь я хочу передать функцию-член еще одного класса в AsyncTask. Эта функция-член будет периодически запускать универсальную функцию. Мне удалось заставить его работать, и вы можете увидеть решение здесь.

class AsyncPeriodicTask {                                                                                                                                                                                    
public:                                                                                                                                                                                                      
     template <class Fn, class... Args>                                                                                                                                                                       
     AsyncPeriodicTask(const std::chrono::milliseconds wait_time, Fn&& inner_func, Args&&... args)                                                                                                            
         : m_stop(false)                                                                                                                                                                                      
         , m_period(wait_time)                                                                                                                                                                                
         , m_task([this, inner_func, tpl = std::make_tuple(std::forward<Args>(args)...)]() { fun(inner_func, tpl); }) {                                                                                       
     }                                                                                                                                                                                                        

     virtual ~AsyncPeriodicTask() { stop(); }                                                                                                                                                                 

     template <class Fn, class... Args>                                                                                                                                                                       
     void fun(Fn&& f, Args&&... args) {                                                                                                                                                                       
        while (!m_stop) {                                                                                                                                                                                    
             std::apply(f, std::forward<Args>(args)...);                                                                                                                                                      
             std::this_thread::sleep_for(m_period);                                                                                                                                                           
         }                                                                                                                                                                                                    
     }                                                                                                                                                                                                        

    void stop() { m_stop = true; }                                                                                                                                                                           

private:                                                                                                                                                                                                     
    std::atomic_bool                m_stop;                                                                                                                                                                  
    const std::chrono::milliseconds m_period;                                                                                                                                                                
    AsyncTask<std::function<void()>> m_task;                                                                                                                                                                 
};                                                  

Я нашел свое решение довольно некрасивым, и я хотел бы улучшить тип и конструкцию m_task. Что-то вроде:

m_task(&AsyncPeriodicTask::fun, this, inner_func, std::forward<Args>(args)...)

и

using MemberFun = void (AsyncPeriodicTask::*)(int);
AsyncTask<MemberFun, Fn, Args ...> m_task;

Я пробовал много вещей, но я не получил тип. У кого-нибудь есть предложение?

...