Welcome back to CodeYourCraft! Today, we're going to dive into a powerful feature of C++17: std::variant. This tool is a game-changer for managing different types of data in a single variable, making your code cleaner, more efficient, and easier to understand.
Let's start with the basics:
std::variant?š” Pro Tip: Think of std::variant as a Swiss Army knife for values. It can hold different types of data, but only one type at a time.
std::variant<int, std::string, double> myVariant;In this example, myVariant can store an int, a std::string, or a double.
std::variantThere are three ways to create and initialize a std::variant:
std::variant.std::variant<int, std::string, double> myVariant;std::variant with the specified initial value.std::variant<int, std::string, double> myVariant(42); // initial value: 42 (of type int)std::variant with the specified initial values.std::variant<int, std::string, double> myVariant = {42, "Hello", 3.14}; // initial value: 42 (of type int)š Note: To access the stored value, you need to use std::get<index>() where index is the position of the type you're interested in. Remember, the first type has index 0.
std::variant<int, std::string, double> myVariant(42);
int value = std::get<0>(myVariant); // value now equals 42To change the stored value, you can assign a new value to the std::variant like any other variable.
std::variant<int, std::string, double> myVariant(42);
myVariant = "New Value"; // myVariant now stores a std::stringstd::visitWhen accessing the stored value, it's essential to check if the std::variant is in a valid state. Use std::holds_alternative<type>() to check if the std::variant contains the desired type. If not, handle the error appropriately.
std::variant<int, std::string, double> myVariant(42);
if (std::holds_alternative<int>(myVariant)) {
int value = std::get<0>(myVariant);
// do something with value
} else if (std::holds_alternative<std::string>(myVariant)) {
std::string value = std::get<1>(myVariant);
// do something with value
} else {
std::cerr << "Error: Unsupported type in std::variant." << std::endl;
}std::visit for Simpler Error Handlingš” Pro Tip: Use std::visit to simplify error handling. It calls a function for the first matching type in the std::variant.
#include <functional>
struct MyVisitor {
void operator()(int value) {
// do something with value
}
void operator()(const std::string& value) {
// do something with value
}
void operator()(double value) {
// do something with value
}
};
std::variant<int, std::string, double> myVariant(42);
std::visit(MyVisitor{}, myVariant);Let's create a simple bank account class that uses std::variant to store the account balance as either an int (for normal accounts) or a std::string (for savings accounts with a fixed interest rate).
#include <string>
#include <variant>
#include <iostream>
struct BankAccount {
std::string name;
std::variant<int, std::string> balance;
BankAccount(const std::string& name, int initialBalance)
: name(name), balance(initialBalance) {}
BankAccount(const std::string& name, const std::string& initialBalance)
: name(name), balance(initialBalance) {}
void deposit(int amount) {
if (std::holds_alternative<int>(balance)) {
int currentBalance = std::get<0>(balance);
balance = currentBalance + amount;
} else {
std::cerr << "Error: Cannot deposit into savings account." << std::endl;
}
}
void deposit(const std::string& amount) {
if (!std::holds_alternative<std::string>(balance)) {
std::cerr << "Error: Cannot deposit into normal account." << std::endl;
} else {
std::string currentBalance = std::get<1>(balance);
// Convert the deposit amount to a double, add the interest, and convert back to a string
double newBalance = std::stod(currentBalance) + 0.01 * std::stod(currentBalance);
balance = newBalance > 1000 ? new std::string(std::to_string(static_cast<int>(newBalance))) : newBalance;
}
}
void printBalance() const {
std::visit([&](auto balanceValue) {
std::cout << name << "'s current balance: " << balanceValue << std::endl;
}, balance);
}
};
int main() {
BankAccount john("John", 500);
john.printBalance();
john.deposit(100);
john.printBalance();
BankAccount savingsAccount("Savings Account", "1000");
savingsAccount.printBalance();
savingsAccount.deposit(50);
savingsAccount.printBalance();
return 0;
}What is `std::variant` in C++17?
How do you access the stored value in a `std::variant`?