一、标准库Thread内容(函数内部实现内容已摘去)
class thread
{ // class for observing and managing threads
public:
class id;
typedef void *native_handle_type;
thread() noexcept;
template<class _Fn,
class... _Args,
class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
{ // construct with _Fx(_Ax...)
_Launch(&_Thr,
_STD make_unique<tuple<decay_t<_Fn>, decay_t<_Args>...> >(
_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));
}
~thread() noexcept;
thread(thread&& _Other) noexcept
: _Thr(_Other._Thr);
thread& operator=(thread&& _Other) noexcept;
thread(const thread&) = delete;
thread& operator=(const thread&) = delete;
void swap(thread& _Other) noexcept;
_NODISCARD bool joinable() const noexcept;
void join();
void detach();
_NODISCARD id get_id() const noexcept;
_NODISCARD static unsigned int hardware_concurrency() noexcept;
_NODISCARD native_handle_type native_handle();
private:
thread& _Move_thread(thread& _Other);
_Thrd_t _Thr;
};
二、Thread类简单介绍
在介绍那个很复杂的构造函数前我们大致了解一下该类。
1、以下含义为thread被创建出来后不能进行拷贝和拷贝赋值,但是有move语义(c++11重要特性)。
thread(thread&& _Other) noexcept
: _Thr(_Other._Thr);
thread& operator=(thread&& _Other) noexcept;
thread(const thread&) = delete;
thread& operator=(const thread&) = delete;
void swap(thread& _Other) noexcept;
2、常用接口(不是本篇的主题,将在另外文章中讲到,请参考:《C++11标准库thread简介》
void join();
void detach();
_NODISCARD id get_id() const noexcept;
_NODISCARD static unsigned int hardware_concurrency() noexcept;
三、复杂而重要的构造函数(本文的主题)
template<class _Fn,
class... _Args,
class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
{ // construct with _Fx(_Ax...)
_Launch(&_Thr,
_STD make_unique<tuple<decay_t<_Fn>, decay_t<_Args>...> >(
_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));
}
1、模板参数部分
template<class _Fn,
class... _Args,
class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>>
1)class _Fn是设想匹配的是可调用对象(函数、成员函数、函数对象、lambda表达式)等。
2)class… _Args,匹配可调用对象的参数列,为C++11的重要特性Variadic Templates(…)和元组tuple。
3)以下内容我们由内到外一层一层分析(对萃取机和元编程要稍作了解)
class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>
a、remove_reference_t<_Fn>为退化_Fn的引用和右值引用。
b、remove_cv_t<#a#>在a的基础上再退化_Fn的const和volatile
c、is_same_v<#b#, thread>在b的基础上判断_Fn和thread是否为同种类型。
d、enable_if_t若c的结果为false则该构造函数模板匹配成功,否则失败,编译不通过。
e、class=#d#为匿名模板参数(一般匿名模板参数来完成对部分参数条件的校验,此处就是经典应用),并且没有占位。
小结:这么一大串是为了不和其他构造发生二义性,使得“1)”中_Fn为可调用对象的设想为真,而不是线程对象。
不同版本VS源码稍有差别,核心思想不会变。
四、延伸探讨
// construct with _Fx(_Ax...)
_Launch(&_Thr,
_STD make_unique<tuple<decay_t<_Fn>, decay_t<_Args>...> >(
_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));
该构造函数的实现部分有兴趣的也可以研究研究。
如有错误或不足欢迎评论指出!创作不易,转载请注明出处。如有帮助,记得点赞关注哦(⊙o⊙)
更多内容请关注个人博客:https://blog.csdn.net/qq_43148810