【问题标题】:C++ - std::decay<T> and std::make_tuple<D> - cannot convert argument from 'D' to 'D &&'C++ - std::decay<T> 和 std::make_tuple<D> - 无法将参数从 'D' 转换为 'D &&'
【发布时间】:2016-10-18 19:47:08
【问题描述】:

我有这个代码:

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
}

GetValue&lt;D&gt;() 根据typeid(D) 从字典返回值,它工作正常,我将MyData 返回到D - 如果我注释掉下一个有问题的行,我对其进行了测试,请参阅下面的问题。

如果我编译这个,T = const MyData &amp; 我得到了这个

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

为什么会产生这个错误以及如何消除它?我只想在我的元组中存储非引用值,即使模板 T 是 refd'。

我可以通过使用std::make_tuple&lt;D&gt;(std::forward&lt;D&gt;(val)) 编译它,但它调用我的移动ctor,我想复制ctor,因为val 在方法结束时被销毁,因此它的内部数据和移动ctor 刚刚移动他们,所以他们走了。

【问题讨论】:

  • 我可以看到希望避免意外调用复制和移动构造函数,但您的移动构造函数应该使原始对象无效以防止出现此问题。如果不能,您可能应该将其删除,因为几乎任何移动构造函数的使用都会中断。

标签: c++ c++11 templates tuples


【解决方案1】:

您永远不应将显式模板参数传递给make_tuplemake_pair。它们的强大之处在于它们推断类型的能力,以及衰减它们和解包引用包装器的能力。

以下应该有效:

std::tuple<D> t = std::make_tuple(std::move(val)); // forward is superfluous here

或者,更好的是:

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

【讨论】:

  • 另外,用auto 替换std::tuple&lt;D&gt; 可能是个好主意。
  • @krzaq 可以编译,但是如果我逐行执行代码,我仍然会进入 move ctor (MyData::MyData(MyData&amp;&amp; other){})
  • @MartinPerry:只要它首先调用复制构造函数,然后调用移动构造函数就可以了(因为您只是在移动副本)。当您将GetValue&lt;D&gt;() 存储到val 时,它应该调用复制构造函数。
  • @Guvante GetValue 调用 copy ctor(创建 A),然后 tuple 调用 move ctor(创建 B).. 但之后,调用 copy (A) dtor 并将数据放入 move (B) 用它
  • @MartinPerry 我认为这取决于您的编译器执行 (N)RVO 的能力,而这又取决于GetValue 的实现。如果你只写std::tuple&lt;D&gt; t{GetValue&lt;D&gt;()}; 会发生什么
猜你喜欢
  • 2011-05-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-09
相关资源
最近更新 更多