基于我之前的问题 here ,我正在写一个小类来帮助我将工作分配给一堆线程。在构造线程时,我想将一个循环计数器作为附加参数传递给参数包以用作 thread_id。这可能吗?
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
}
最佳答案
如 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
绑定(bind)为 fn
的参数。
这将导致类似于以下的函数调用:
fn(thread_id, args...);
一般,如果您想将一些参数绑定(bind)到一个函数并获得一个新的可调用对象来包装前一个参数,您需要使用 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)...
)
);
关于c++ - 将附加参数包装到 c++11 中的可变参数包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34437566/