可变参数构造函数优先于用户提供的移动构造函数,除非默认

Variadic constructor is being preferred to the user provided move constructor except when defaulted

本文关键字:构造函数 移动 默认 参数 变参 优先于 用户      更新时间:2023-10-16

考虑以下代码片段,其中我有一个仅移动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)) {}
                                                ^

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

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

这是

意料之中的。查看您的代码:

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

在您的情况下,T 是 int。您想如何从Wrapper<int>初始化int