C++ 线程构造函数周围的可变模板包装器无法编译
我正在尝试编译以下程序C++ 线程构造函数周围的可变模板包装器无法编译,c++,templates,function-pointers,variadic-templates,C++,Templates,Function Pointers,Variadic Templates,我正在尝试编译以下程序 #include <iostream> #include <thread> struct State { State (std::string message) : message (message) { } template <class Function, class... Args> void spawn (Function&& function, Args&am
#include <iostream>
#include <thread>
struct State
{
State (std::string message) : message (message)
{
}
template <class Function, class... Args>
void
spawn (Function&& function, Args&&... args)
{
std::thread t (&State::run <Function, Args...>, this, function, args...);
t . join ();
}
template <class Function, class... Args>
void
run (Function&& function, Args&&... args)
{
std::cout << this -> message << std::endl;
function (args...);
}
~State () = default;
std::string message;
};
void
print (std::string message)
{
std::cout << message << std::endl;
}
int main (int argc, char ** argv)
{
State state ("Hello, World!\n");
state.spawn (print, "Goodbye, World!\n");
return 0;
}
当我尝试使用Clang6.0.1编译它时,我得到以下输出
$ clang++ main.cpp
In file included from main.cpp:2:
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../include/c++/8.2.0/thread:242:40: error:
no matching member function for call to '_M_invoke'
-> decltype(std::declval<_Invoker&>()._M_invoke(_Indices()))
~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../include/c++/8.2.0/thread:127:8: note:
in instantiation of template class
'std::thread::_Invoker<std::tuple<void (State::*)(void
(&)(std::__cxx11::basic_string<char>), char const (&)[17]), State *,
void (*)(std::__cxx11::basic_string<char>), const char *> >'
requested here
__make_invoker(std::forward<_Callable>(__f),
^
main.cpp:14:15: note: in instantiation of function template specialization
'std::thread::thread<void (State::*)(void
(&)(std::__cxx11::basic_string<char>), char const (&)[17]), State *,
void (&)(std::__cxx11::basic_string<char>), char const (&)[17]>'
requested here
std::thread t (&State::run <Function, Args...>, thi...
^
main.cpp:41:8: note: in instantiation of function template specialization
'State::spawn<void (&)(std::__cxx11::basic_string<char>), char const
(&)[17]>' requested here
state.spawn (print, "Goodbye, World!\n");
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../include/c++/8.2.0/thread:231:4: note:
candidate template ignored: substitution failure [with _Ind = <0, 1,
2, 3>]: no matching function for call to '__invoke'
_M_invoke(_Index_tuple<_Ind...>)
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../include/c++/8.2.0/thread:186:13: error:
type 'std::thread::_Invoker<std::tuple<void (State::*)(void
(&)(std::__cxx11::basic_string<char>), char const (&)[17]), State *,
void (*)(std::__cxx11::basic_string<char>), const char *> >' does not
provide a call operator
_M_run() { _M_func(); }
^~~~~~~
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../include/c++/8.2.0/thread:182:2: note:
in instantiation of member function
'std::thread::_State_impl<std::thread::_Invoker<std::tuple<void
(State::*)(void (&)(std::__cxx11::basic_string<char>), char const
(&)[17]), State *, void (*)(std::__cxx11::basic_string<char>), const
char *> > >::_M_run' requested here
_State_impl(_Callable&& __f) : _M_func(std::forward<_Callab...
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../include/c++/8.2.0/thread:197:24: note:
in instantiation of member function
'std::thread::_State_impl<std::thread::_Invoker<std::tuple<void
(State::*)(void (&)(std::__cxx11::basic_string<char>), char const
(&)[17]), State *, void (*)(std::__cxx11::basic_string<char>), const
char *> > >::_State_impl' requested here
return _State_ptr{new _Impl{std::forward<_Callable>(__f)}};
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../include/c++/8.2.0/thread:126:25: note:
in instantiation of function template specialization
'std::thread::_S_make_state<std::thread::_Invoker<std::tuple<void
(State::*)(void (&)(std::__cxx11::basic_string<char>), char const
(&)[17]), State *, void (*)(std::__cxx11::basic_string<char>), const
char *> > >' requested here
_M_start_thread(_S_make_state(
^
main.cpp:14:15: note: in instantiation of function template specialization
'std::thread::thread<void (State::*)(void
(&)(std::__cxx11::basic_string<char>), char const (&)[17]), State *,
void (&)(std::__cxx11::basic_string<char>), char const (&)[17]>'
requested here
std::thread t (&State::run <Function, Args...>, thi...
^
main.cpp:41:8: note: in instantiation of function template specialization
'State::spawn<void (&)(std::__cxx11::basic_string<char>), char const
(&)[17]>' requested here
state.spawn (print, "Goodbye, World!\n");
^
2 errors generated.
我说不出我做错了什么。我可以看出编译器似乎不喜欢我传递给thread对象的第一个参数,但我不知道为什么或者如何修复它
我尝试将函数从成员函数引用更改为静态成员函数引用,并添加结构指针作为附加参数。这对产量没有实质性影响
我也尝试过用GCC编译它,看看它是否告诉我一些有趣的事情。它似乎与clang的代码有相同的问题,但输出更加冗长,对我来说也同样不容易理解
为什么我的程序不编译?此错误消息试图告诉我什么?之所以出现此错误,是因为std::thread decay会在调用初始函数之前复制给定给其构造函数的参数。您正在传入一个包含16个字符的字符串文字,外加一个终止null,即const char[17]类型的左值。此表达式的衰减副本生成const char*类型的prvalue,这是通常的数组到指针的转换。但是,您告诉std::thread使用run函数,仍然需要const char&[17]参数。这个数组到指针的衰减是不可逆的,因此您无法从std::thread的衰减副本获取所需的左值 下面是如何编写代码片段以进行编译的示例:
template <class Function, class... Args>
void
spawn (Function&& function, Args&&... args)
{
std::thread t (&State::run <std::decay_t<Function>, std::decay_t<Args>...>, this, std::forward<Function>(function), std::forward<Args>(args)...);
t . join ();
}
template <class Function, class... Args>
void
run (Function function, Args... args)
{
std::cout << this -> message << std::endl;
function(args...);
}
这里,我们正在实例化State::run和decayed类型,确保传递一个具有适当签名的函数,以接收std::thread将提供的decayed复制参数。这显然与您如何使用引用有关,特别是在显式模板中,我在阅读后对这一点有点猜测。谢谢你为我解释清楚。我自己也不能这么做。好的,但是只要我从spawn中删除右值引用注释,程序也可以在spawn中没有模板参数上的decation\t和forward注释的情况下编译。为什么呢?根据你的解释,似乎不应该这样。我不能在这里解释,但请发另一个问题,也许我会回答