variant、optional和any 这三个模板类是用来取代C风格的一些不安全的代码
optional —— 持有T或为空
variant<T,U> —— 持有T或U(类似于union)
any —— 持有任意类型(类似于void*)
std::optional<int> var1 = 7;
std::variant<int,string> var2 = 7;
std::any var3 = 7;
auto x1 = *var1 ; // 对 optional 解引用
auto x2 = std::get<int>(var2); // 像访问 tuple 一样访问 variant
auto x3 = std::any_cast<int>(var3); // 转换 any
variant
std::variant 表示一个类型安全的联合体(变化体)std::variant
的一个实例在任意时刻要么保有它的一个可选类型之一的值,要么在错误情况下无值
// C风格
union variant{
int,
char
}
// C++风格
typedef std::variant<int,char> variant;
visit
以一或多个 variant 所保有的各实参调用所提供的函数对象
示例
int main() {
// 创建一个 std::variant 变量,可以存放 int 或 char 类型的值,并初始化为整数 1022。
std::variant<int, char> variant = 1022;
// 使用 std::visit 访问 variant 中的值,根据存储的类型输出不同的消息。
std::visit(
[](auto &&arg) {
if (std::is_same_v<std::decay_t<decltype(arg)>, int>) {
printf("variant中存放的是int类型"); // 如果存放的是int类型,输出此消息。
} else if (std::is_same_v<std::decay_t<decltype(arg)>, char>) {
printf("variant中存放的是char类型"); // 如果存放的是char类型,输出此消息。
}
},
variant);
// 将 variant 的值更改为字符 'A'。
variant = 'A';
// 再次使用 std::visit 访问 variant 中的值,根据存储的类型输出不同的消息。
std::visit(
[](auto &&arg) {
if (std::is_same_v<std::decay_t<decltype(arg)>, int>) {
printf("variant中存放的是int类型"); // 如果存放的是int类型,输出此消息。
} else if (std::is_same_v<std::decay_t<decltype(arg)>, char>) {
printf("variant中存放的是char类型"); // 如果存放的是char类型,输出此消息。
}
},
variant);
}
这里只是给出部分示例,因为有些我自己还没看明白,所以后面会更新的
holds_alternative
检查某个 variant 是否当前持有某个给定类型
示例
int main() {
// 创建一个 std::variant 变量,可以存放 int 或 char 类型的值,并初始化为整数 1022。
std::variant<int, char> variant = 1022;
// 检查 variant 中是否存放的是 int 类型的值。
if (std::holds_alternative<int>(variant)) {
// 如果存放的是 int 类型的值,使用 std::get<int> 获取它,并以整数格式输出。
printf("%d\n", std::get<int>(variant));
} else if (std::holds_alternative<char>(variant)) {
// 如果存放的是 char 类型的值,使用 std::get<char> 获取它,并以字符格式输出。
printf("%c\n", std::get<char>(variant));
}
// 将 variant 的值更改为字符 'A'。
variant = 'A';
// 检查 variant 中是否存放的是 int 类型的值。
if (std::holds_alternative<int>(variant)) {
// 如果存放的是 int 类型的值,使用 std::get<int> 获取它,并以整数格式输出。
printf("%d\n", std::get<int>(variant));
} else if (std::holds_alternative<char>(variant)) {
// 如果存放的是 char 类型的值,使用 std::get<char> 获取它,并以字符格式输出。
printf("%c\n", std::get<char>(variant));
}
}
std::get(std::variant)
以给定索引或类型(如果类型唯一)读取 variant 的值,错误时抛出异常
示例
int main() {
// 创建一个 std::variant 变量,可以存放 int 或 char 类型的值,并初始化为整数 1022。
std::variant<int, char> variant = 1022;
// 使用get函数获取值并输出
printf("%d\n", std::get<int>(variant));
}
optional
std::optional 管理一个可选的容纳值,既可以存在也可以不存在的值
// C风格
int optional = NULL;
// C++风格
std::optional<int> optional = std::nullopt;
has_value
检查对象是否含值
示例
int main() {
std::optional<int> optional = std::nullopt;
if (!optional.has_value()) {
// 如果optional为空就输出
printf("optional为空");
}
}
any
std::any 描述用于任何可拷贝构造类型的单个值的类型安全容器
// C风格
int value = 10;
void *any = &value;
// C++风格
std::any any = 10;
has_value
检查对象是否含有值
示例
int main() {
std::any any = 10;
if (any.has_value()) {
// 如果any不为空就输出
printf("any不为空\n");
}
}
type
返回所含值的 typeid
示例
int main() {
std::any any = 10;
if (any.type() == typeid(int)) {
// any中存放的是int则输出
printf("any中存放的是int类型\n");
}
}
any_cast
对被容纳对象的类型安全访问
示例
int main() {
std::any any = 10;
if (any.type() == typeid(int)) {
// any中存放的是int则输出
printf("any中存放的是%d\n",std::any_cast<int>(any));
}
}
目前variant、optional和any的使用也就这么点,后续我还会补充一些我遗漏的内容
About this Post
This post is written by JinHong Zeng, licensed under CC BY-NC 4.0.