Ответ 1
Это пример условного включения перегрузки с помощью SFINAE.
Эта перегрузка не должна учитываться при разрешении перегрузки, если первый аргумент имеет тип std::thread
.
Обратите внимание, что исходный исходный код стандартных заголовков С++ не предназначен для чтения. Он также не предназначен для мимизации. Разработчики компилятора С++ могут делать много вещей в своих реализациях std-заголовков, которые вы не можете и не должны делать за пределами этих заголовков. Наименьшая из которых запускает переменную с _
, за которой следует буква верхнего регистра (которая запрещена в коде пользователя).
Изучите тип аргумента по умолчанию, если _Fn
- это std::thread
, ссылка на него или ссылка на cv, измененную таким же образом.
typename enable_if<
!is_same<typename decay<_Fn>::type, thread>::value>::type>
decay<_Fn>::type
разделяет ссылки и квалификацию cv. Он также преобразует ссылки на функции в указатели на функцию и ссылки на массивы на указатели на первый элемент, но это не важно здесь.
Предположим, что _Fn
было 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
является потоком, он является ложным, поэтому при разрешении перегрузки возникает сбой замены.
SFINAE означает, что сбой замены не является ошибкой, и вместо жалобы компилятора он просто удаляет эту перегрузку с рассмотрения. И thread(thread const&)
(который я считаю =delete
ed) вместо этого найден конструктор.