The following sample builds and runs properly with the line Container container2(container1); removed. It appears the copy constructor for std::variant itself is deleted, which makes my Container's copy constructor implicitly deleted.
Effectively, I'm asking:
std::variant as a member?Container before safe copy/move assignment is allowed?#include <string>
#include <variant>
class A {};
class Container {
public:
Container(int i) : data_(i) {}
Container(float f) : data_(f) {}
Container(std::string s) : data_(s) {}
Container(std::unique_ptr<A> a) : data_(std::move(a)) {}
std::variant<int, float, std::string, std::unique_ptr<A>> data_;
};
int main() {
Container container1{3};
// error: call to implicitly-deleted copy constructor of 'Container'
//
// copy constructor of 'Container' is implicitly deleted because
// field 'data_' has a deleted copy constructor
Container container2(container1);
return 0;
}
cppreference has this to say about std::variant's copy constructor:
Copy constructor. [...] This constructor is defined as deleted unless
std::is_copy_constructible_v<T_i>is true for allT_iinTypes. [...]
In other words, it is not deleted unless one or more of the types that the std::variant can contain is not copyable for whatever reason. In your case, it's the std::unique_ptr that's causing the problem. Perhaps std::shared_ptr would be more appropriate.
Extending Paul Sanders' answer: what kind of copy do you want?
If it is a shallow copy, use shared_ptr<A>.
If it is a deep copy, why not have variant<..,A>? If the reason is that A is polymorphic, then the real problem is cloning each of the derived classes. You have to create your own mechanism for the cloning and your own copyable smart pointer to use it - as far as I know, there is nothing in the standard library to help you.
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