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 available
When 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.
Answers to questions are automatically generated and may not have been reviewed.
std::variant
Learn how to store dynamic data types in C++ using unions and the type-safe std::variant