How can I default construct a variant with non-default-constructible types?
If I have a std::variant with types that are not default-constructible, how can I still default construct the variant?
If you have a std::variant that contains types that are not default-constructible, you can still default construct the variant by including std::monostate as one of the variant's alternative types.
std::monostate is a special type designed for this purpose. It's an empty struct that is always default-constructible. By including it as the first alternative in your variant, you ensure that the variant itself is default-constructible, even if the other types are not.
Here's an example:
#include <variant>
struct NonDefaultConstructible {
NonDefaultConstructible() = delete;
NonDefaultConstructible(int x) {}
};
int main() {
// This fails because NonDefaultConstructible
// is not default-constructible
std::variant<NonDefaultConstructible> v;
// This works because std::monostate is
// default-constructible
std::variant<std::monostate,
NonDefaultConstructible> v;
// You can still emplace other types
v.emplace<NonDefaultConstructible>(42);
}error: 'std::variant<NonDefaultConstructible>::variant': no appropriate default constructor availableWhen you default construct a variant with std::monostate, the variant will initially hold a std::monostate value. You can then assign or emplace one of the other types into the variant as needed.
Keep in mind that std::monostate is a distinct type, so you need to handle it in your visitor functions or when retrieving values from the variant. But it's a small price to pay for the ability to default construct variants with non-default-constructible types.
Constrained Dynamic Types using Unions and std::variant
Learn how to store dynamic data types in C++ using unions and the type-safe std::variant