2015-12-23 102 views
3

基於我剛纔的問題here,我寫一個小班幫我分配工作一堆線程。在構造線程時,我想將循環計數器作爲附加參數傳遞給要用作thread_id的參數包。這可能嗎?包裝附加參數在C可變參數參數包++ 11

qthread.h

#ifndef QTHREAD_H 
#define QTHREAD_H 

#include <vector> 
#include <thread> 
#include <memory> 

class qthread 
{ 
    std::vector <std::shared_ptr <std::thread>> threads; 
public: 
    // Constructor 
    template <class Fn, class... Args> 
    qthread(Fn&& fn, Args&&... args) 
    { 
     size_t maxNumThreads = std::thread::hardware_concurrency() - 1; 
     for(size_t i = 0; i < maxNumThreads; i++) 
     { 
      // While constructing the thread I would like to also pass i as a thread_id to the function in the parameter packing 
      threads.push_back(std::make_shared <std::thread>(std::forward<Fn>(fn), std::forward<Args>(args)...)); 
     } 
    } 
    // Destructor 
    ~qthread() 
    { 
     for(auto thr_p:threads) 
     { 
      thr_p->join(); 
     } 
    } 
}; 

#endif /* QTHREAD_H */ 

main.cpp

#include <iostream> 

#include "qthread.h" 

void test(const size_t thread_id, int x) 
{ 
    for(size_t i=0; i < 1000; i++) 
    { 
     x += i; 
    } 
    std::cout << "thread: " << thread_id << ", total: " << x << "\n"; 
} 

int main() 
{ 
    qthread(test, 5); // Distribute the 'test' task to n threads -- note that this doesn't work in this case since the function requires two parameters 
} 
+0

你真的不想轉發rvalue參數*多次*。他們會第一次搬家。 –

+0

建議做什麼? – ruser45381

回答

4

正如在評論中提到由T.C.,有a std::thread constructor具有以下特徵:

template< class Function, class... Args > 
explicit thread(Function&& f, Args&&... args); 

此構造函數會調用拷貝/移動功能f和參數args...其線程訪問的存儲,然後調用f(args...)在新線程。

這足以使用...

threads.push_back(
    std::make_shared <std::thread>(
     std::forward<Fn>(fn), thread_id, std::forward<Args>(args)... 
    ) 
) 

...綁定thread_id作爲fn參數。

這將導致類似於函數調用:

fn(thread_id, args...); 

一般,如果你想要一些參數綁定到一個功能,並獲得一個新的可調用對象,將包裹以前一,你想用lambda或struct

C++ 14例如(假設線程id是第一個參數)

threads.push_back(
    std::make_shared <std::thread>(
     [thread_id, &fn](auto&&... args) -> decltype(auto) 
     { 
      // "Bind" `_thread_id` as first argument of `fn`. 
      return std::forward<Fn>(fn)(thread_id, 
       std::forward<decltype(args)>(args)...); 
     }, 
     std::forward<Args>(args)... 
    ) 
); 

C++ 11例如(假設線程id是第一個參數)

template<typename TF> 
struct bind_thread_id 
{ 
    TF _fn; 
    int _thread_id; 

    bind_thread_id(TF fn, int thread_id) 
     : _fn(fn), _thread_id(thread_id) 
    { 
    } 

    template<typename... Ts> 
    auto operator()(Ts&&... xs) 
    { 
     // "Bind" `_thread_id` as first argument of `fn`. 
     fn(_thread_id, std::forward<Ts>(xs)...); 
    } 
}; 

// ... 

threads.push_back(
    std::make_shared <std::thread>(
     bind_thread_id<Fn>{fn, thread_id}, 
     std::forward<Args>(args)... 
    ) 
); 
+0

等待,這有什麼錯'threads.push_back(STD :: make_shared (標準::向前(FN)的thread_id,性病::向前(參數)...));'? –

+0

@ T.C。我認爲他想打電話'fn'用'ARGS ...'**和**'thread_id' - 至少,這就是我理解的問題。像'fn(thread_id,args ...)'或'fn(args ...,thread_id)'。 –

+0

...,只是堅持'thread_id'在'性病的參數列表:: thread'的構造不會這麼做,因爲...? –