Try with
template<typename... T>
auto foo(T&&... t){
[](T&&... u){ }(std::forward<T>(t)...); // (1)
return std::thread( // (2)
[](auto &&... u){ },
std::forward<T>(t)...
);
}
I mean: in the lambda you pass to std::thread(), auto && ... instead of T && .... Or, maybe, T const & ....
I'm not a language layer, and maybe someone can correct me, but it seems to me that there is a clash between universal references and r-value references. And the fact that std::thread() pass copies of the following arguments to the first one.
When you write
template<typename... T>
auto foo(T&&... t)
the && are universal-references and T... become int, when you call foo(1), and int &, when you call foo(n).
Inside the function you get
[](int){ }(std::forward<int>(t)); // (1)
return std::thread( // (2)
[](int){ },
std::forward<int>(t)...
);
in case f(0).
And this works because both lambda are waiting a int by copy and this ever works.
But when you call f(n), inside foo() you get
[](int &){ }(std::forward<int>(t)); // (1)
return std::thread( // (2)
[](int &){ },
std::forward<int>(t)...
);
and this works for the first call, because the lambda wait a int left-reference variable (int &) and get a int left-reference variable, but doesn't works for the second call because std::thread pass a copy of std::forward<int>(t) (so a right-reference, int &&) to the lambda that wait for a left-reference.