【发布时间】:2015-03-23 00:52:30
【问题描述】:
std::thread 的构造函数和类似的接口,如std::async 将它们的参数复制到线程可访问的存储中,就像通过函数一样
template <class T>
typename decay<T>::type decay_copy(T&& v) {
return std::forward<T>(v);
}
这个函数可以处理移动和复制构造函数,但我想知道是否可以概括这些参数的构造方式,类似于.emplace() 在标准容器接口中概括.insert()。
例如,我可能有一个只能从int 构造的可移动类型:
struct foo
{
foo(int arg){}
foo(foo&& other){}
foo() = delete;
foo(const foo&) = delete;
};
是否可以为这样的类型创建一个helper,通过decay_copy 进行复制构造会产生构造其他类型的效果?
我知道如何创建一个解决方案,将foo 的参数复制到线程可访问的存储中,但我想避免这种情况(假设这些参数通常很大并且线程可访问的存储很少)。
这是我最初的尝试:
#include <thread>
#include <utility>
struct foo
{
foo(int arg){}
foo(foo&& other){}
foo() = delete;
foo(const foo&) = delete;
};
template<class T, class Arg>
struct helper
{
operator T () const
{
return T{arg_};
}
Arg arg_;
};
template<class T, class Arg>
helper<T,Arg> help(Arg&& arg)
{
return helper<T,Arg>{std::forward<Arg>(arg)};
}
int main()
{
auto lambda = [](const foo& f){};
std::thread t{lambda, help<foo>(13)};
t.join();
return 0;
}
这个解决方案的问题是foo 的所有构造函数参数都通过helper 对象复制到线程可访问的存储中。我只想在foo 对象上花费存储空间。
假设我不能修改lambda,也不能修改std::thread,当给定helper作为参数时,是否有一些技巧会导致decay_copy函数返回一个新构造的foo?
【问题讨论】:
-
你想让
std::thread通过调用构造函数的线程创建一个foo类型的对象,但是在新线程的存储上? -
@dyp:基本上是的。理想情况下,构造函数参数的存储只存在于父线程的堆栈中,
foo对象的存储在子线程的堆栈中。 -
@JaredHoberock:那么,正如我在回答中所说,为什么不在父级中创建
foo并将其移动到线程中? -
@rodrigo:很难解释。我没有那个选项——构造函数取决于执行它的线程 ID。
-
我认为
std::thread的界面不支持这个。在内部,它需要为Bob设置一些存储并在那里构造对象,以便Bob可以在其主线程函数中访问它们。但似乎std::thread仅支持将一个参数复制或移动到Bob相同(衰减)类型的存储上的一个对象。
标签: c++ multithreading templates parameter-passing