C++ std::thread 参数在转换为右值后必须是可调用的
C++ std::thread arguments must be invocable after conversion to rvalues
我对这里发生的事情一无所知
这是一个简单的代码示例,说明了我要实现的目标:
main.cpp
#include <iostream>
#include <thread>
int main(int argc, char** argv) {
constexpr int SIZE = 10;
std::array<int, SIZE> arr{0};
auto add = []<typename T>(std::array<T, SIZE>& arr) {
for (int i = 0; i < SIZE; i++)
arr[i] = i + 1;
};
std::thread t1(std::ref(add), std::ref(arr));
t1.join();
return 0;
}
编译命令:
g++ -std=c++20 -Wall main.cpp -pthread -o t1
错误:
In file included from /usr/include/c++/11.1.0/stop_token:35,
from /usr/include/c++/11.1.0/thread:40,
from main.cpp:2:
/usr/include/c++/11.1.0/bits/std_thread.h: In instantiation of ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >; _Args = {std::reference_wrapper<std::array<int, 10> >}; <template-parameter-1-3> = void]’:
main.cpp:15:48: required from here
/usr/include/c++/11.1.0/bits/std_thread.h:130:72: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
130 | typename decay<_Args>::type...>::value,
| ^~~~~
/usr/include/c++/11.1.0/bits/std_thread.h:130:72: note: ‘std::integral_constant<bool, false>::value’ evaluates to false
/usr/include/c++/11.1.0/bits/std_thread.h: In instantiation of ‘struct std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >’:
/usr/include/c++/11.1.0/bits/std_thread.h:203:13: required from ‘struct std::thread::_State_impl<std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > > >’
/usr/include/c++/11.1.0/bits/std_thread.h:143:29: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >; _Args = {std::reference_wrapper<std::array<int, 10> >}; <template-parameter-1-3> = void]’
main.cpp:15:48: required from here
/usr/include/c++/11.1.0/bits/std_thread.h:252:11: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >::__result<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >’
252 | _M_invoke(_Index_tuple<_Ind...>)
| ^~~~~~~~~
/usr/include/c++/11.1.0/bits/std_thread.h:256:9: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >::__result<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >’
256 | operator()()
| ^~~~~~~~
注:
如果我将 lambda 更改为:
auto add = []<typename T>(std::array<T, SIZE> arr)
并像这样调用线程:
std::thread t1(std::ref(add), arr);
它编译了,但显然数组没有改变,因为它是一个副本而不是引用
std::reference_wrapper
不是std::array
,所以无法推导出T
。
add(std::ref(arr));
也不编译。
你可能会用到
std::thread t1([&](auto arg){ add(arg.get()); }, std::ref(arr));
我对这里发生的事情一无所知
这是一个简单的代码示例,说明了我要实现的目标:
main.cpp
#include <iostream>
#include <thread>
int main(int argc, char** argv) {
constexpr int SIZE = 10;
std::array<int, SIZE> arr{0};
auto add = []<typename T>(std::array<T, SIZE>& arr) {
for (int i = 0; i < SIZE; i++)
arr[i] = i + 1;
};
std::thread t1(std::ref(add), std::ref(arr));
t1.join();
return 0;
}
编译命令:
g++ -std=c++20 -Wall main.cpp -pthread -o t1
错误:
In file included from /usr/include/c++/11.1.0/stop_token:35,
from /usr/include/c++/11.1.0/thread:40,
from main.cpp:2:
/usr/include/c++/11.1.0/bits/std_thread.h: In instantiation of ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >; _Args = {std::reference_wrapper<std::array<int, 10> >}; <template-parameter-1-3> = void]’:
main.cpp:15:48: required from here
/usr/include/c++/11.1.0/bits/std_thread.h:130:72: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
130 | typename decay<_Args>::type...>::value,
| ^~~~~
/usr/include/c++/11.1.0/bits/std_thread.h:130:72: note: ‘std::integral_constant<bool, false>::value’ evaluates to false
/usr/include/c++/11.1.0/bits/std_thread.h: In instantiation of ‘struct std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >’:
/usr/include/c++/11.1.0/bits/std_thread.h:203:13: required from ‘struct std::thread::_State_impl<std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > > >’
/usr/include/c++/11.1.0/bits/std_thread.h:143:29: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >; _Args = {std::reference_wrapper<std::array<int, 10> >}; <template-parameter-1-3> = void]’
main.cpp:15:48: required from here
/usr/include/c++/11.1.0/bits/std_thread.h:252:11: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >::__result<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >’
252 | _M_invoke(_Index_tuple<_Ind...>)
| ^~~~~~~~~
/usr/include/c++/11.1.0/bits/std_thread.h:256:9: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >::__result<std::tuple<std::reference_wrapper<main(int, char**)::<lambda(std::array<T, 10>&)> >, std::reference_wrapper<std::array<int, 10> > > >’
256 | operator()()
| ^~~~~~~~
注:
如果我将 lambda 更改为:
auto add = []<typename T>(std::array<T, SIZE> arr)
并像这样调用线程:
std::thread t1(std::ref(add), arr);
它编译了,但显然数组没有改变,因为它是一个副本而不是引用
std::reference_wrapper
不是std::array
,所以无法推导出T
。
add(std::ref(arr));
也不编译。
你可能会用到
std::thread t1([&](auto arg){ add(arg.get()); }, std::ref(arr));