2

I have a class that I want to be able to construct with a temporary unique_ptr, like this:

MyCollection foo(std::unique_ptr<MyObj>(nullptr));

The object should take ownership of the pointer. My question is, what is the correct constructor signature for this?

1. MyCollection(std::unique_ptr<MyObj> foo);
2. MyCollection(std::unique_ptr<MyObj>&& foo); 

The first option does not link. The second does, however what happens if I go with this, and then try to construct MyCollection with a non R-value? ie

std::unique_ptr<MyObj> pointer(nullptr);
MyCollection(pointer);

The answer here: How do I pass a unique_ptr argument to a constructor or a function? suggests that I should take the unique_ptr by value, but as I said above, it does not link in VS2010 (the error looks like this...

Error   5   error LNK2028: unresolved token (0A00075A) "private: __thiscall std::unique_ptr<class IVDSDocCore,struct std::default_delete<class IVDSDocCore> >::unique_ptr<class IVDSDocCore,struct std::default_delete<class IVDSDocCore> >(class std::unique_ptr<class IVDSDocCore,struct std::default_delete<class IVDSDocCore> > const &)" (??0?$unique_ptr@VIVDSDocCore@@U?$default_delete@VIVDSDocCore@@@std@@@std@@$$FAAE@ABV01@@Z) referenced in function "public: static void __clrcall std::unique_ptr<class IVDSDocCore,struct std::default_delete<class IVDSDocCore> >::<MarshalCopy>(class std::unique_ptr<class IVDSDocCore,struct std::default_delete<class IVDSDocCore> > *,class std::unique_ptr<class IVDSDocCore,struct std::default_delete<class IVDSDocCore> > *)" (?<MarshalCopy>@?$unique_ptr@VIVDSDocCore@@U?$default_delete@VIVDSDocCore@@@std@@@std@@$$FSMXPAV12@0@Z)  C:\sviluppo\FerrariGes\GesDB\VDS.NET\VDS\vdsdoc.obj

Some replies suggest I need to use the move function. If I use constructor 1, and try to create the object like this:

If I use constructor 1, and try to create the object like this:

MyCollection foo(move(std::unique_ptr<MyObj>(nullptr)));

I get the same link error.

Community
  • 1
  • 1
Tom Davies
  • 2,386
  • 3
  • 27
  • 44

1 Answers1

0

Youa re right that you should accept the unique_ptr by value, but since it cannot be copied, you have to move it into the constructor:

MyCollection(std::unique_ptr<MyObj> foo);

//..
std::unique_ptr<MyObj> pointer(/*something*/);
MyCollection(std::move(pointer));

Edit my bad, I just noticed I overread the first use of the constructor.

MyCollection foo(std::unique_ptr<MyObj>(nullptr)); 

should work, of course, with the constructor taking the unique_ptr by value.

However, the function signature mentioned in the linker error looks a bit weird to me, it basically is

void __clrcall unique_ptr<X>::<MarshalCopy>(unique_ptr<X>*, unique_ptr<X>*)

So maybe it's a completely different issue. I'm not very firm with CLR, so forgive me if I am wrong: Are you using unique_ptr in C++/CLI? Is that supported? What does <MarshalCopy> do internally - looks like something generated, maybe it does not work for move-only types?

This could be related:Linker error when using unique_ptr in C++/CLI

Community
  • 1
  • 1
Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
  • Yes, this is my understanding. So, I'm confused about the link error! – Tom Davies Feb 28 '13 at 15:35
  • I think it must be related to this. The app is a mix of managed and unmanaged C++. As in the link you posted, using the && constructor works ok. No idea why, and no time to figure it out now. Thanks. – Tom Davies Feb 28 '13 at 16:14