I get Compiler Error C2248 when i try to compile the following code:
#include <list>
#include <memory>
using namespace std;
class data
{
public:
static data parse()
{
data d;
data::parse(d);
return d;
}
list<std::unique_ptr<data>> l;
private:
static void parse(data& node)
{ }
};
int main()
{
return 0;
}
Why? How can i fix this?
Note: I have no problem using std::shared_ptr
instead of std::unique_ptr
.
You need to provide move operations for your type:
data(data&& other)
: l(std::move(other.l))
{
}
data& operator=(data&& other)
{
l = std::move(other.l);
return *this;
}
And, since you'll have added a user-declared constructor, you'll also need a user-declared default constructor:
data() { }
My understanding is that your code is correct as-is, per the final C++11 language standard. Visual C++ does not fully implement the final specification for when move operations are implicitly generated (as of the Visual C++ 2012 RC). The specification for when implicit move operations are generated changed several times very late in the standardization process.
If you have a class type C
that has any data member that is movable but noncopyable, Visual C++ will not generate an implicit move constructor or move assignment operator, and the implicit copy constructor and copy assignment operator are both suppressed by the presence of the move-only data member. In other words, if you want ot aggregate move-only types, you must provide the move operations for the aggregating class yourself.
(At least, this is my understanding from experimentation with the compiler.)
First things first, VC++ doesn't automatically generate a move ctor and move assignment operator yet, which means you need to define them yourself.
Next, when you return local variables, the compiler first tries to move them before actually going the usual route of copying them. However, to do that, it needs a move ctor. Since it doesn't have that, it tries the usual copy and through the generated copy ctor automatically invokes the copy constructor of std::list
which in turn tries to invoke the copy ctor of its element type, which is private in std::unique_ptr
s case.
You need to either define an appropriate move ctor or a copy ctor that doesn't invoke std::unique_ptr
's copy ctor (i.e., make a deep copy of the content).
Short answer: (C++11 specific) Items in a list
must be copyable or movveable. A unique_ptr
is not copyable by-design, but it is moveable, so long as the controlled type is also moveable.
Your type, data
is not moveable because you have not implemented move semantics and the compiler did not do it for you.
Implement move semantics, and you can use unique_ptr
in a list
:
data(ddata&&) {};
According to thhe Standard, a move constructor would be generated for your class by the compiler. However, VS10 does not support this -- this might be the problem your'e running in to.
For further reference, see my post on CR: Canonical Implementation of Move Semantics
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With