我正在编写自己的基本游戏引擎,并且正在对其进行多线程处理。我创建了一个RawThread
对象,该对象用消息队列等包装了std::thread
。我想将这些RawThread
映射到一个id(unsigned int
)。因此,我尝试将一个插入std::map<unsigned int, RawThread>
中,但是却遇到了一堆非常模棱两可的模板错误。如果我注释掉map.insert行,那么代码可以很好地编译,一切正常,但是我希望能够像在RawThread
中尝试的那样,将main()
插入地图。
我已经看了一个小时的代码,检查我的RawThread构造函数模板是否错误,或者是否正确使用了引用/指针,但是看不到问题。
#include <map>
#include <utility>
#include <thread>
class RawThread
{
public:
RawThread(const RawThread& you)
{
*this = you;
}
~RawThread()
{
delete mThread;
}
template<class Function, class... Args>
RawThread(Function&&f, Args&&... args)
{
mThread = new std::thread(std::forward<Function>(f),
std::forward<Args>(args)...);
}
const RawThread& operator=(const RawThread& in)
{
this->mThread = in.mThread;
return *this;
}
void join()
{
mThread->join();
}
std::thread* mThread;
};
void hello(int x){while(true)++x;}
int main()
{
int arg = 0;
RawThread myThread(&hello, arg);
unsigned int threadId = 0;
std::map<unsigned int, RawThread> threadMap;
threadMap.insert(std::make_pair(threadId, myThread));
return 0;
}
我看到一个令人讨厌的错误,因此将其放在pastebin上:https://pastebin.com/9A4wN7kL
答案 0 :(得分:1)
insert
的问题是通过调用
RawThread
的副本
template<class Function, class... Args>
RawThread(Function&&f, Args&&... args)
然后Function
是RawThread
的实例,而Args
为空。 std::thread
构造函数可以将object的实例作为其第一个参数,但是此实例的类必须提供operator()()
作为线程的主体。您的班级缺少这一点。您可以添加它,然后代码就会编译。
class RawThread {
//....
void operator()() {}
};
但这不是您想要的。
对我来说,您应该以仅此类的一个实例保持活动RawThread
指针的方式实现mThread
。 RawThread
仅应移动,副本应被禁用。如果许多实例共享相同的mThread
值,应该调用哪个实例来加入或删除该对象?
仅支持移动的版本可能是:
#include <map>
#include <utility>
#include <thread>
class RawThread {
public:
~RawThread()
{
if (mThread)
{
if (mThread->joinable())
mThread->join();
delete mThread;
}
}
RawThread(RawThread&& theOther) {
mThread = theOther.mThread;
theOther.mThread = nullptr;
}
RawThread& operator=(RawThread&& theOther) {
mThread = theOther.mThread;
theOther.mThread = nullptr;
return *this;
}
template<class Function, class... Args>
RawThread(Function&&f, Args&&... args) {
mThread = new std::thread(std::forward<Function>(f),
std::forward<Args>(args)...);
}
void join() {
mThread->join();
}
std::thread* mThread;
};
void hello(int x){while(true)++x;}
int main()
{
int arg = 0;
RawThread myThread(&hello, arg);
unsigned int threadId = 0;
std::map<unsigned int, RawThread> threadMap;
threadMap.emplace(threadId,std::move(myThread)); // move object into map
return 0;
}
答案 1 :(得分:0)
#include <map>
#include <utility>
#include <thread>
#include <memory>
class RawThread
{
public:
template<class Function, class... Args>
RawThread(Function&&f, Args&&... args)
{
mThread = std::make_shared<std::thread>(std::forward<Function>(f),
std::forward<Args>(args)...);
}
RawThread(const RawThread &)=default;
RawThread(RawThread &&)=default;
RawThread()=delete;
void join()
{
mThread->join();
}
std::shared_ptr<std::thread> mThread;
};
void hello(int x){while(true)++x;}
int main()
{
int arg = 0;
RawThread myThread(&hello, arg);
unsigned int threadId = 0;
std::map<unsigned int, RawThread> threadMap;
//This line is wrong because it uses the constructor template instead of the copy constructor
//threadMap.insert(std::make_pair(threadId, myThread);
threadMap.insert(std::make_pair(threadId, (const RawThread &)myThread));//Good, it uses the copy constructor
threadMap.insert(std::make_pair(threadId, std::move(myThread)));//Good, it uses the move constructor
return 0;
}