Попробуйте с
template<typename... T>
auto foo(T&&... t){
[](T&&... u){ }(std::forward<T>(t)...); // (1)
return std::thread( // (2)
[](auto &&... u){ },
std::forward<T>(t)...
);
}
Я имею в виду: в лямбде вы переходите на std::thread()
, auto && ...
вместо T && ...
.Или, может быть, T const & ...
.
Я не являюсь языковым слоем, и, возможно, кто-то может исправить меня, но мне кажется, что существует конфликт между универсальными ссылками и ссылками на r-значения.И тот факт, что std::thread()
передает копии следующих аргументов в первый аргумент.
Когда вы пишете
template<typename... T>
auto foo(T&&... t)
, &&
являются универсальными ссылкамии T...
становятся int
, когда вы звоните foo(1)
, и int &
, когда вы звоните foo(n)
.
Внутри функции вы получаете
[](int){ }(std::forward<int>(t)); // (1)
return std::thread( // (2)
[](int){ },
std::forward<int>(t)...
);
в случаеf(0)
.
И это работает, потому что обе лямбды ждут копию int
, и это всегда работает.
Но когда вы звоните f(n)
, внутри foo()
вы получаете
[](int &){ }(std::forward<int>(t)); // (1)
return std::thread( // (2)
[](int &){ },
std::forward<int>(t)...
);
, и это работает для первого вызова, потому что лямбда ожидает переменную левой ссылки int
(int &
) и получает переменную левой ссылки int
, но не работает длявторой вызов, потому что std::thread
передает копию из std::forward<int>(t)
(так что ссылка справа int &&
) в лямбду, ожидающую ссылку слева.