【问题标题】:Variadic constructor is being preferred to the user provided move constructor except when defaulted可变参数构造函数优于用户提供的移动构造函数,除非默认情况下
【发布时间】:2018-03-18 17:37:51
【问题描述】:

考虑下面的 sn-p 代码,其中我有一个仅移动的 Wrapper 对象,该对象将参数转发到构造的基础数据。现在,如果我在另一个仅移动类(本例中为 SomeObject)中使用此 Wrapper 对象,除非 SomeObject 的移动构造函数是默认的,否则它不会编译。

#include <utility>

template <typename T> class Wrapper {
public:
  template <typename... Args>
  Wrapper(Args &&... args) : _data{std::forward<Args>(args)...} {}

  Wrapper(const Wrapper &) = delete;

  Wrapper(Wrapper &&other) : _data(std::move(other)) {}

  T &get() const { return _data; }

protected:
  T _data;
};

struct SomeObject {
  SomeObject(const SomeObject &) = delete;
  SomeObject(SomeObject &&other) : x(std::move(other.x)) {}
  //SomeObject(SomeObject &&other) = default; // this works!
  SomeObject(int val) : x(val) {}

  Wrapper<int> x;
};

int main() {
  SomeObject obj(10);
  return 0;
}

使用 gcc 6.3 我们得到:

test.cpp: In instantiation of ‘Wrapper<T>::Wrapper(Wrapper<T>&&) [with T = int]’: 
test.cpp:20:56:   required from here 
test.cpp:10:52: error: cannot convert ‘std::remove_reference<Wrapper<int>&>::type {aka Wrapper<int>}’ to ‘int’ in initialization
Wrapper(Wrapper &&other) : _data(std::move(other)) {}
                                                ^

我在这里缺少什么吗?用户在SomeObject 中提供的移动构造函数不与编译器在默认时定义的相同吗?

我能找到的唯一接近于此的是this answer,但我觉得这是一个不同的情况,因为我的SomeObject 的移动构造函数没有传递const 类型。

【问题讨论】:

  • 使用Wrapper(Wrapper &amp;&amp;other) : _data(std::move(other._data)) {}

标签: c++ c++11 templates variadic-templates move-semantics


【解决方案1】:

这是意料之中的。看看你的代码:

Wrapper(Wrapper &&other) : _data(std::move(other)) {}
T _data;

在你的情况下,T 是 int。你想如何从Wrapper&lt;int&gt;初始化int

【讨论】:

  • 更明确地说,将std::move(other) 更改为std::move(other._data)
猜你喜欢
  • 2020-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-02
  • 2016-09-02
  • 1970-01-01
  • 2010-10-30
  • 2016-12-16
相关资源
最近更新 更多