I'm trying to dllexport
a type with a std container of std::unique_ptr
member, f.e.
struct __declspec(dllexport) C {
std::vector<std::unique_ptr<int>> c_;
};
but whatever i try, msvc always complains about
msvc/14.33.31629/include\xutility(4145): error C2280: 'std::unique_ptr<int,std::default_delete<int>> &std::unique_ptr<int,std::default_delete<int>>::operator =(const std::unique_ptr<int,std::default_delete<int>> &)': attempting to reference a deleted function
The container type doesn't matter; the error is almost identical (always C2280) for vector, map, and others.
However, as soon as a std::unique_ptr
member is added to the type, f.e.
struct __declspec(dllexport) C {
std::vector<std::unique_ptr<int>> c_;
std::unique_ptr<int> rup;
};
the error disappears.
I have no clue if this is the intended behavior, what causes this problem and how it can be fixed without adding a random std::unique_ptr
member. What am i missing?
CodePudding user response:
When you have a member std::vector<std::unique_ptr<int>> c_;
, the compiler will provide a copy assignment operator C& operator=(const C&)
that will try to copy the c_
member. This will fail to compile if it is actually used, since the elements of c_
can't be copied.
__declspec(dllexport)
seems to try to create this implicitly-declared function (maybe to export it? Though it doesn't seem to actually do that), which fails.
When you add std::unique_ptr<int> rup;
, this is a type without a copy constructor at all, so the implicit operator=(const C&)
is suppressed (The move assign operator C& operator=(C&&)
can still be used).
You can get rid of the implicit copy-assign operator by declaring a move-assign operator or a move constructor:
struct __declspec(dllexport) C {
std::vector<std::unique_ptr<int>> c_;
C(C&&) = default;
};
Or by inheriting from a move-only type/having a move-only member:
struct move_only { constexpr move_only(move_only&&) noexcept = default; };
struct __declspec(dllexport) C : private move_only {
std::vector<std::unique_ptr<int>> c_;
};
CodePudding user response:
unique_ptr
is not a copyable type (or else it wouldn't be unique). The error message is complaining that something is trying to access the unique_ptr
's copy assignment operator, which has been disabled.
In your first example, your C
struct has only copyable members, so a default copy constructor and copy assignment operator are generated for it by the compiler. Which then fails if they are invoked since unique_ptr
can't be copied.
Whereas in your second example, your C
struct has a non-copyable member, so the default copy constructor and copy assignment operator are not generated by the compiler.