C++ - std :: decay <T>和std :: make_tuple <D> - 无法将参数从'D'转换为'D &&'

Mar*_*rry 3 c++ templates tuples c++11

我有这个代码:

template <typename T>
void someFunction(){
   typedef std::decay<T>::type D;

   D val = GetValue<D>();
   std::tuple<D> t = std::make_tuple<D>(val);

   //... tuple is stored outside this scope in global variable
}
Run Code Online (Sandbox Code Playgroud)

GetValue<D>()基于从字典返回值上typeid(D),它工作正常,我回到MyData到D-我测试了它,如果我注释掉下一个问题的行,见下面的问题.

如果我编译它,因为T = const MyData &我得到了这个

 error C2664: 'std::tuple<MyData > std::make_tuple<D>(D &&)': cannot convert argument 1 from 'D' to 'D &&'
Run Code Online (Sandbox Code Playgroud)

为什么会产生此错误以及如何删除它?我想在我的元组中只存储非ref值,即使模板T是refd'.

我可以通过使用来编译它std::make_tuple<D>(std::forward<D>(val)),但是它调用我的移动ctor并且我想要复制ctor,因为val在方法结束时被销毁,所以它的内部数据和移动ctor只是移动它们,所以它们就消失了.

krz*_*zaq 5

你永远不应该将显式模板参数传递给make_tuple和make_pair.它们的强大之处在于它们能够推断出类型,以及衰减它们和展开参考包装器.

以下应该有效:

std::tuple<D> t = std::make_tuple(std::move(val)); // forward is superfluous here
Run Code Online (Sandbox Code Playgroud)

或者,更好的是:

auto t = std::make_tuple(GetValue<D>());
Run Code Online (Sandbox Code Playgroud)