Mar*_*ata 3 c++ icc c++11 stdthread
我想包装一个对std :: thread构造函数的调用(以跟踪所有运行的线程,以便我可以加入它们或做其他事情).在此示例中,t1线程正确构造,但t2线程不使用gcc 4.8.1.但是,在Windows(VS2012)上,它编译时没有错误,并且运行没有错误.基于此处的讨论,这似乎是gcc中的一个错误,但可以说它实际上是VS中的一个错误.这样做的正确方法是什么?
#include <iostream>
#include <thread>
class A {
public:
void foo(int n ) { std::cout << n << std::endl; }
};
template<class F, class Arg>
std::thread& wrapper(F&& f, Arg&& a)
{
std::thread* t = new std::thread(f,a,100);
return *t;
}
int main()
{
A a;
std::thread t1(&A::foo, &a, 100);
t1.join();
std::thread t2 = wrapper(&A::foo, &a);
t2.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是编译器错误
-bash-4.1$ make
g++ -std=c++11 main.cpp -o main
main.cpp: In function ‘int main()’:
main.cpp:23:41: error: use of deleted function ‘std::thread::thread(std::thread&)’
std::thread t2 = wrapper(&A::foo, &a);
^
In file included from main.cpp:2:0:
/opt/rh/devtoolset-2/root/usr/include/c++/4.8.1/thread:125:5: error: declared here
thread(thread&) = delete;
^
make: *** [all] Error 1
Run Code Online (Sandbox Code Playgroud)
我在这里问了一个错误的问题并准备将其删除,但由于答案很有帮助,我会离开它.问题是英特尔icpc 14.0编译器(不是gcc 4.8.1)引发了与bind此处讨论的相同的错误.它与"包装器"无关,只是用成员函数而不是静态函数调用std :: thread.
关于内存泄漏的投诉是100%有效的,但那是我对该示例进行了不幸的简化(来自我的真实代码).实际代码将线程保存在容器中,并在销毁时删除线程.
这是一个更好的例子:
#include <iostream>
#include <thread>
class A {
public:
void foo() { }
template<class Function, class Arg>
std::thread* wrapper(Function&& f, Arg&& a)
{
auto t = new std::thread(f,a);
return t;
}
};
int main()
{
A a;
std::thread t1(&A::foo, &a);
t1.join();
std::thread* t2 = a.wrapper(&A::foo, &a);
t2->join();
delete t2;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并且g++(4.8.1)的输出有效
-bash-4.1$ make CXX=g++
g++ -lpthread -std=c++11 main.cpp -o main
Run Code Online (Sandbox Code Playgroud)
和英特尔编译器icpc(14.0)的输出不起作用
-bash-4.1$ make CXX=icpc
icpc -lpthread -std=c++11 main.cpp -o main
/opt/rh/devtoolset-2/root/usr/include/c++/4.8.1/functional(1697): error: class "std::result_of<std::_Mem_fn<void (A::*)()> (A *)>" has no member "type"
typedef typename result_of<_Callable(_Args...)>::type result_type;
^
detected during:
instantiation of class "std::_Bind_simple<_Callable (_Args...)> [with _Callable=std::_Mem_fn<void (A::*)()>, _Args=<A *>]" at line 1753
instantiation of "std::_Bind_simple_helper<_Callable, _Args...>::__type std::__bind_simple(_Callable &&, _Args &&...) [with _Callable=void (A::*)(), _Args=<A *>]" at line 137 of "/opt/rh/devtoolset-2/root/usr/include/c++/4.8.1/thread"
instantiation of "std::thread::thread(_Callable &&, _Args &&...) [with _Callable=void (A::*)(), _Args=<A *>]" at line 20 of "main.cpp"
/opt/rh/devtoolset-2/root/usr/include/c++/4.8.1/functional(1726): error: class "std::result_of<std::_Mem_fn<void (A::*)()> (A *)>" has no member "type"
typename result_of<_Callable(_Args...)>::type
^
detected during:
instantiation of class "std::_Bind_simple<_Callable (_Args...)> [with _Callable=std::_Mem_fn<void (A::*)()>, _Args=<A *>]" at line 1753
instantiation of "std::_Bind_simple_helper<_Callable, _Args...>::__type std::__bind_simple(_Callable &&, _Args &&...) [with _Callable=void (A::*)(), _Args=<A *>]" at line 137 of "/opt/rh/devtoolset-2/root/usr/include/c++/4.8.1/thread"
instantiation of "std::thread::thread(_Callable &&, _Args &&...) [with _Callable=void (A::*)(), _Args=<A *>]" at line 20 of "main.cpp"
compilation aborted for main.cpp (code 2)
make: *** [all] Error 2
-bash-4.1$
Run Code Online (Sandbox Code Playgroud)
你的包装应该是这样的:
template<class F, class Arg>
std::thread wrapper(F&& f, Arg&& a)
{
return std::thread(std::forward<F>(f), std::forward<Arg>(a));
}
Run Code Online (Sandbox Code Playgroud)