C++ 根据函数签名将变量模板中的类型转发为值/引用
这个问题涉及到,并且可能涉及 我有一个类,其中C++ 根据函数签名将变量模板中的类型转发为值/引用,c++,variadic-templates,stdthread,perfect-forwarding,C++,Variadic Templates,Stdthread,Perfect Forwarding,这个问题涉及到,并且可能涉及 我有一个类,其中AddFunction方法接收一个函数和该函数的参数列表,然后生成一个std::thread,用传递的参数调用传递的函数: class Processes { public: Processes() {} ~Processes() { for (auto &t : threads_) { t.join(); } } template <class Function, typename...
AddFunction
方法接收一个函数和该函数的参数列表,然后生成一个std::thread
,用传递的参数调用传递的函数:
class Processes {
public:
Processes() {}
~Processes() {
for (auto &t : threads_) {
t.join();
}
}
template <class Function, typename... Args>
void AddFunction(Function &&func, Args &&... args) {
threads_.emplace_back(std::forward<Function>(func),
std::forward<Args>(args)...);
}
private:
std::vector<std::thread> threads_;
}
但这会导致不正确的行为,因为lambda在通过值传递值之前通过引用捕获值,从而导致通过引用捕获行为
如何实现根据目标函数签名将参数作为值或引用转发的函数
例如:
voidfoo(inta,std::vector const&b){/*…*/}
int main(){
过程;
INTA=6;
std::载体b;
procs.AddFunction(
福,
a、 //应按值传递
b//应通过引用传递(由std::ref实现)
);
返回0;
}
您可以将函数签名更改为不太通用:
首先是一些助手:
template <typename T> struct non_deducible { using type = T; };
template <typename T> using non_deducible_t = typename non_deducible<T>::type;
template <typename T>
auto passed_by(T& t, std::true_type)
{
return std::ref(t);
}
template <typename T>
T&& passed_by(T&& t, std::false_type)
{
return std::forward<T>(t);
}
模板结构不可推断{using type=T;};
使用non_deducible_t=typename non_deducible::type的模板;
模板
自动通过(T&T,标准::真实类型)
{
返回std::ref(t);
}
模板
T&&T通过(T&&T,标准::错误类型)
{
返回std::向前(t);
}
然后
template <class Ret, typename... Args>
void AddFunction(Ret (*func)(Args...), non_deducible_t<Args>... args) {
threads_.emplace_back(func,
passed_by(std::forward<Args>(args),
std::is_reference<Args>{})...);
}
模板
void AddFunction(Ret(*func)(参数…,不可推断的参数){
线程放置回(函数,
通过(标准::转发(args),
std::is_reference{})…);
}
如果您想沿着lambda路线走下去,您可以实现一些实用程序,这意味着右值被移动到闭包中,左值通过引用被捕获。您可以使用std::tuple
存储T
或T&
(我的链接文章有一个更清晰的实现):
模板
void AddFunction(函数和函数,参数和…参数)
{
线程。将线程放置回([
targs=std::tuple这解决了问题。我不知道你可以用这种方式解压函数调用。什么是{}
语法?那只是一个空构造函数吗?谢谢!是的,类型{}
是类型
的空构造函数,使用{}
语法可以避免在某些情况下与类型()相反的麻烦解析
(即使在这里两者都可以工作)。
template <typename T> struct non_deducible { using type = T; };
template <typename T> using non_deducible_t = typename non_deducible<T>::type;
template <typename T>
auto passed_by(T& t, std::true_type)
{
return std::ref(t);
}
template <typename T>
T&& passed_by(T&& t, std::false_type)
{
return std::forward<T>(t);
}
template <class Ret, typename... Args>
void AddFunction(Ret (*func)(Args...), non_deducible_t<Args>... args) {
threads_.emplace_back(func,
passed_by(std::forward<Args>(args),
std::is_reference<Args>{})...);
}
template <class Function, typename... Args>
void AddFunction(Function &&func, Args &&... args)
{
threads_.emplace_back([
targs = std::tuple<Args...>{std::forward<Args>(args)...},
tfunc = std::tuple<Function>(func)]() mutable
{
std::apply([&targs](auto&& x_func)
{
std::apply([&x_func](auto&&... x_args)
{
std::forward<Function>(x_func)(
std::forward<Args>(x_args)...
);
}, targs);
}, tfunc);
});
}