- 起因
- 问题
- 问题原因
- 解决方案
- 附
线程创建的主体是函数,现在创建一个带缺省参数的函数,再用来创建线程
// void* lpParam 传递this指针
// WPARAM wpParam 传递的参数
void Run(void* lpParam, WPARAM wpParam = NULL)
{...}
std::thread* hThread = new std::thread(Run, std::move(this), 1);
当然这样是对的,编译可以通过,现在是以下代码有问题
std::thread* hThread = new std::thread(Run, std::move(this));问题
错误 C2672 “std::invoke”: 未找到匹配的重载函数 错误 C2893 未能使函数模板“unknown-type std::invoke(_Callable &&,_Types &&...) noexcept(问题原因)”专用化
首先想当然的认为std::thread不认识这个缺省函数,意味着std:thread不能补充缺省参数
那就先看看std::thread的construct
thread() noexcept
{ // construct with no thread
_Thr_set_null(_Thr);
}
template>, thread>>>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
{ // construct with _Fx(_Ax...)
_Launch(&_Thr,
_STD make_unique, decay_t<_Args>...> >(
_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));
}
重点看第二个construct函数
先直接看主体参数部分
// class _Fn 函数 // class... _Args 可变参数 explicit thread(_Fn&& _Fx, _Args&&... _Ax)
单就可变参数这一项似乎就与缺省参数存在冲突
再看函数主体流程
_Launch(&_Thr, _STD make_unique, decay_t<_Args>...> >( _STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...)); -->调用_Launch函数 template inline void _Launch(_Thrd_t *_Thr, _Target&& _Tg) { // launch a new thread _LaunchPad<_Target> _Launcher(_STD forward<_Target>(_Tg)); _Launcher._Launch(_Thr); } -->调用_Launcher._Launch函数 void _Launch(_Thrd_t *_Thr) { // launch a thread _Thrd_startX(_Thr, _Call_func, this); while (!_Started) _Cnd_waitX(_Cond, _Mtx); } -->调用_Thrd_startX使用底层的_Thrd_start创建线程,这里直接看调用函数处理部分 static unsigned int __stdcall _Call_func(void *_Data) { // entry point for new thread static_cast<_Pad *>(_Data)->_Go(); return (0); } -->调用_Go下调用_Run(this) static void _Run(_LaunchPad *_Ln) noexcept // enforces termination { // construct local unique_ptr and call function object within _Target _Local(_STD forward<_Target>(_Ln->_MyTarget)); _Ln->_Release(); _Execute(*_Local, make_index_sequence >()); _Cnd_do_broadcast_at_thread_exit(); } -->这里再调用_Execute template static void _Execute(typename _Target::element_type& _Tup, index_sequence<_Idxs...>) { // invoke function object packed in tuple _STD invoke(_STD move(_STD get<_Idxs>(_Tup))...); }
现在找到了源头再去回溯
倒数第二步
_Execute(*_Local, make_index_sequence>());
这里是对可变参数进行整数化序列,现在就相当于对之前的
// void* lpParam 传递this指针
// WPARAM wpParam 传递的参数
void Run(void* lpParam, WPARAM wpParam = NULL)
{...}
参数整数化序列,这里应该有两个
而在编译期间
std::thread* hThread = new std::thread(Run, std::move(this));
提供的数量只有一个,所以报错,这里实际上的结果是对函数参数的左值进行序列,而对右值不序列,所以导致这里编译报错;而根本原因可能还是
// class _Fn 函数 // class... _Args 可变参数 explicit thread(_Fn&& _Fx, _Args&&... _Ax)
可变参数无法进行缺省化,想到python的参数就可以可变且可省,只是速度有点慢罢了。
解决方案既然可变无法缺省,那么就不使用缺省,改为
// void* lpParam 传递this指针
// WPARAM wpParam 传递的参数
void Run(void* lpParam, WPARAM wpParam)
{...}
std::thread* hThread = new std::thread(Run, std::move(this), 1);
如果有多个,就都必须给出参数具体的值,比如接下来
std::thread* hThread1 = new std::thread(Run, std::move(this), 2);
虽然感觉有点麻烦,但还是这样吧。
附头文件
#include
跟踪路径
--> -->
底层的
_CRTIMP2_PURE void __cdecl _Thrd_abort(const char *); _CRTIMP2_PURE int __cdecl _Thrd_start(_Thrd_imp_t *, _Thrd_callback_t, void *);
应该是闭源的



