现代C++ 21 any
文章目录
- 1. **概述**
- 2. **成员函数**
- 2.1 **构造函数和析构函数**
- 2.2 **修改器函数**
- 2.3 **观察者函数**
- 3. **非成员函数**
- 4. **辅助类**
- 5. **示例代码**
- 示例 1:基本用法
- 输出:
- 示例 2:使用 `std::any_cast` 访问值
- 输出:
- 示例 3:使用 `std::any_cast` 获取指针
- 输出:
- 示例 4:使用 `std::make_any` 创建 `std::any` 对象
- 输出:
- 示例 5:使用 `reset` 清空 `std::any` 对象
- 输出:
- 6. **总结**
std::any
是 C++17 引入的一个类,用于表示一个类型安全的容器,可以存储任何可复制构造类型的单个值。它提供了一种灵活的方式来处理不同类型的对象,而不需要提前知道具体的类型。
std::any
的设计目标是提供一种通用的、类型安全的方式来进行值的存储和访问。
1. 概述
std::any
的定义如下:
class any;
std::any
可以存储任何满足构造函数要求的类型的实例,或者为空。- 存储的实例称为包含对象。
- 如果两个
std::any
对象的状态都为空,或者两个状态都不为空且包含的对象是等价的,则这两个状态是等价的。 std::any
鼓励实现避免对小型对象进行动态分配,但这可能只适用于std::is_nothrow_move_constructible
返回true
的类型。
2. 成员函数
2.1 构造函数和析构函数
- 默认构造函数:创建一个空的
std::any
对象。 - 带参数的构造函数:接受一个值或引用,初始化
std::any
以包含该值。 - 赋值操作符:将一个
std::any
的内容赋值给另一个std::any
,或者将一个值赋值给std::any
。 - 析构函数:销毁
std::any
对象及其包含的值。
2.2 修改器函数
emplace()
:就地构造std::any
中的值,避免不必要的拷贝或移动。reset()
:销毁std::any
中的包含对象,使其变为空状态。swap()
:交换两个std::any
对象的内容。
2.3 观察者函数
has_value()
:检查std::any
是否包含值。如果包含值,返回true
;否则返回false
。type()
:返回std::any
中包含值的typeid
,如果std::any
为空,则返回typeid(void)
。
3. 非成员函数
std::swap(std::any)
:专门化std::swap
算法,用于交换两个std::any
对象的内容。std::make_any<T>(args...)
:方便的函数模板,用于创建std::any
对象,并直接构造其包含的值。std::any_cast<T>(std::any)
:类型安全的访问std::any
中的包含对象。std::any_cast
可以用于获取值、指针或引用。如果类型不匹配,抛出std::bad_any_cast
异常。
4. 辅助类
std::bad_any_cast
:当std::any_cast
的返回值形式在类型不匹配时抛出的异常。
5. 示例代码
示例 1:基本用法
#include <iostream>
#include <any>
#include <typeinfo>
int main() {
// 创建一个 std::any 对象并存储 int 类型的值
std::any a = 42;
std::cout << "Type: " << a.type().name() << ", Value: " << std::any_cast<int>(a) << '\n';
// 修改为 double 类型的值
a = 3.14;
std::cout << "Type: " << a.type().name() << ", Value: " << std::any_cast<double>(a) << '\n';
// 修改为 bool 类型的值
a = true;
std::cout << "Type: " << a.type().name() << ", Value: " << std::any_cast<bool>(a) << '\n';
return 0;
}
输出:
Type: i, Value: 42
Type: d, Value: 3.14
Type: b, Value: true
示例 2:使用 std::any_cast
访问值
#include <iostream>
#include <any>
#include <string>
int main() {
// 创建一个 std::any 对象并存储 string 类型的值
std::any a = std::string("Hello, World!");
// 使用 std::any_cast 获取值
if (a.has_value()) {
std::string value = std::any_cast<std::string>(a);
std::cout << "Value: " << value << '\n';
}
// 尝试访问不存在的类型,会抛出 std::bad_any_cast 异常
try {
int value = std::any_cast<int>(a);
} catch (const std::bad_any_cast& e) {
std::cout << "Error: " << e.what() << '\n';
}
return 0;
}
输出:
Value: Hello, World!
Error: bad any_cast
示例 3:使用 std::any_cast
获取指针
#include <iostream>
#include <any>
#include <string>
int main() {
// 创建一个 std::any 对象并存储 int 类型的值
std::any a = 42;
// 使用 std::any_cast 获取指向值的指针
if (a.has_value()) {
int* p = std::any_cast<int>(&a);
std::cout << "Pointer to value: " << *p << '\n';
}
// 修改为 double 类型的值
a = 3.14;
// 使用 std::any_cast 获取指向值的指针
if (a.has_value()) {
double* p = std::any_cast<double>(&a);
std::cout << "Pointer to value: " << *p << '\n';
}
return 0;
}
输出:
Pointer to value: 42
Pointer to value: 3.14
示例 4:使用 std::make_any
创建 std::any
对象
#include <iostream>
#include <any>
#include <string>
int main() {
// 使用 std::make_any 创建 std::any 对象并存储 string 类型的值
std::any a = std::make_any<std::string>("Hello, World!");
// 使用 std::any_cast 获取值
if (a.has_value()) {
std::string value = std::any_cast<std::string>(a);
std::cout << "Value: " << value << '\n';
}
return 0;
}
输出:
Value: Hello, World!
示例 5:使用 reset
清空 std::any
对象
#include <iostream>
#include <any>
int main() {
// 创建一个 std::any 对象并存储 int 类型的值
std::any a = 42;
std::cout << "Type: " << a.type().name() << ", Value: " << std::any_cast<int>(a) << '\n';
// 清空 std::any 对象
a.reset();
if (!a.has_value()) {
std::cout << "No value\n";
}
return 0;
}
输出:
Type: i, Value: 42
No value
6. 总结
std::any
是 C++17 引入的一个非常灵活的工具,特别适用于需要存储和处理不同类型值的场景。它的主要特点包括:
- 类型安全:通过
std::any_cast
提供了类型安全的访问方式,确保只能访问与实际存储类型匹配的值。 - 灵活性:可以存储任何可复制构造类型的值,甚至可以在运行时动态改变存储的类型。
- 性能优化:鼓励实现避免对小型对象进行动态分配,减少内存开销。
- 简洁易用:提供了简单的接口来管理值的存储、访问和修改。
如果你有更多具体的问题或需要进一步的帮助,请随时提问!