具有模板化构造函数的 C++ 自定义线程包装器导致插入 std::map 时出现编译时错误
C++ Custom Thread Wrapper with Templatized Constructor causes compile time error for insertion into std::map
我正在编写自己的基本游戏引擎,并且正在对其进行多线程处理。我创建了一个 RawThread
对象,它用消息队列等包装了一个 std::thread
。我想将这些 RawThread
映射到一个 id(unsigned int
)。所以我尝试将一个插入到 std::map<unsigned int, RawThread>
中,但我得到了一堆非常模棱两可的模板错误。如果我注释掉 map.insert 行,那么代码编译得很好,一切正常,但我希望能够将 RawThread
插入地图,如 main()
中所尝试的那样。
我盯着这段代码看了一个小时,检查我的 RawThread 构造函数模板是否有误,或者我是否错误地使用了 references/pointer,但我看不出问题所在.
#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
#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;
}
insert
的问题是 RawThread
的副本是通过调用
创建的
template<class Function, class... Args>
RawThread(Function&&f, Args&&... args)
那么 Function
是 RawThread
的实例,而 Args
是空的。 std::thread
构造函数可以将对象的实例作为其第一个参数,但是此实例的 class 必须提供 operator()()
作为线程的主体。您的 class 缺少它。您可以添加它,代码将编译。
class RawThread {
//....
void operator()() {}
};
但这不是你想要的。
对我来说,您应该以 class 的只有一个实例保持活动 mThread
指针的方式实现 RawThread
。 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;
}
我正在编写自己的基本游戏引擎,并且正在对其进行多线程处理。我创建了一个 RawThread
对象,它用消息队列等包装了一个 std::thread
。我想将这些 RawThread
映射到一个 id(unsigned int
)。所以我尝试将一个插入到 std::map<unsigned int, RawThread>
中,但我得到了一堆非常模棱两可的模板错误。如果我注释掉 map.insert 行,那么代码编译得很好,一切正常,但我希望能够将 RawThread
插入地图,如 main()
中所尝试的那样。
我盯着这段代码看了一个小时,检查我的 RawThread 构造函数模板是否有误,或者我是否错误地使用了 references/pointer,但我看不出问题所在.
#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
#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;
}
insert
的问题是 RawThread
的副本是通过调用
template<class Function, class... Args>
RawThread(Function&&f, Args&&... args)
那么 Function
是 RawThread
的实例,而 Args
是空的。 std::thread
构造函数可以将对象的实例作为其第一个参数,但是此实例的 class 必须提供 operator()()
作为线程的主体。您的 class 缺少它。您可以添加它,代码将编译。
class RawThread {
//....
void operator()() {}
};
但这不是你想要的。
对我来说,您应该以 class 的只有一个实例保持活动 mThread
指针的方式实现 RawThread
。 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;
}