Consider the following snippet of code where I have a move-only Wrapper
object that forwards the arguments to the underlying data on construction. Now if I use this Wrapper
object inside another move-only class (SomeObject
in this case), unless the move constructor for SomeObject
is defaulted, it doesn't compile.
#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;
}
With gcc 6.3 we get:
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)) {}
^
Is there something I am missing here? Aren't the user provided move constructor in SomeObject
the same as the one the compiler would define when defaulted?
The only thing close to this that I could find is this answer but I feel like this is a different case since my move constructor for SomeObject
isn't passing const
types.