这是std::thread
构造函数声明的方式(使用Visual Studio 2015):
template<class _Fn,
class... _Args,
class = typename enable_if<
!is_same<typename decay<_Fn>::type, thread>::value>::type>
explicit thread(_Fn&& _Fx, _Args&&... _Ax)
关于_Fn
和_Args
的问题,但是,第三个class = ...
完全混淆了我。它做了什么,它是如何工作的以及它的用途是什么?
答案 0 :(得分:16)
这是使用SFINAE有条件启用重载的示例。
如果第一个参数的类型为std::thread
,则不应考虑此重载进行重载解析。
请注意,C ++标准标题的原始来源无意读取。它也无意模仿。 C ++编译器实现者可以在他们的std头实现中做很多事情,你不能也不应该在这些头之外做。其中最少的是使用_
后跟大写字母(在用户代码中禁止)的变量。
如果_Fn
是std::thread
,对typename enable_if<
!is_same<typename decay<_Fn>::type, thread>::value>::type>
的引用或对修改过的cv的引用,请检查默认参数的类型。
decay<_Fn>::type
_Fn
剥离了引用和cv资格。它还将对函数的引用转换为指向函数的指针和将引用转换为指向第一元素的指针,但这在此并不重要。
假设thread&
为typename enable_if<
!is_same<typename decay<thread&>::type, thread>::value>::type>
typename enable_if<
!is_same<thread, thread>::value>::type>
typename enable_if<
!true>::type>
typename enable_if<
false>::type>
/* substitution failure occurs */>
。我会评估:
enable_if<B>::type
B
仅在true
为_Fn
时才存在;当thread(thread const&)
是一个线程时,它是假的,因此在重载解析期间存在替换失败。
SFINAE意味着替换失败不是错误,而不是编译器抱怨,它只是从考虑中删除了这个重载。而是找到=delete
(我认为是'%r'
ed)构造函数。
答案 1 :(得分:5)
第3个未命名的模板参数有一个默认值,用于通过constructor of std::thread满足SFINAE的以下要求,以避免在调用移动构造函数时出现干扰。 / p>
如果
std::decay_t<Function>
与std::thread
的类型相同,则此构造函数不参与重载解析。