как конструктор std:: thread обнаруживает ссылку rvalue?
Очевидно, что можно передать ссылку rvalue в конструктор std::thread
. Моя проблема заключается в определении этого конструктора в cppreference. Он говорит, что этот конструктор:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
Создает новый объект std::thread и связывает его с потоком исполнение. Сначала конструктор копирует / перемещает все аргументы (оба объект функция f и все аргументы...) к потоко-доступному хранилищу, как если бы по функции:
template <class T>
typename decay<T>::type decay_copy(T&& v) {
return std::forward<T>(v);
}
Насколько я могу проверка:
std::is_same<int, std::decay<int&&>::type>::value
Возвращает true. Это означает, что std::decay<T>::type
отбросит ссылочную часть аргумента rvalue. Тогда как std::thread
конструктор знает, какой аргумент передается ссылками lvalue или rvalue? Потому что все T&
и T&&
будут преобразованы в T
через std::decay<T>::type
3 ответа:
auto s = std::decay_copy(std::string("hello"));
Эквивалентно:
template<> std::string std::decay_copy<std::string>(std::string&& src) { return std::string(std::move(src)); } std::string s = decay_copy<std::string>(std::string("hello"));
Конструктор
std::thread
знает категорию значений своих аргументов, потому что он знает, что такоеFunction
иArgs...
, которые он использует для идеальной передачи своих параметров вdecay_copy
(или эквивалент).Фактическая функция потока не знает категории значения. Он всегда вызывается как rvalue, со всеми аргументами rvalue - что имеет смысл: копии
f
иargs...
являются локальными для потока и больше нигде не будут использоваться.
Это общая проблема совершенной переадресации. Если вы хотите восстановить информацию о rvalue в функции, вы должны использовать std:: forward std::forward. Если вас интересует определение типа значения, вы можете прочитать этуvalue_category . Из описания можно найти информацию о том, как компилятор распознает rvalue, xvalue, lvalue, prvalue, gvalue во время компиляции.