此头文件是通用工具库的一部分。类 any
描述一种可用于任何可复制构造类型的单个值的类型安全容器。
1) 类 any
的对象存储满足构造函数要求的任何类型的一个实例或为空,这被称为 any
类对象的状态。存储的实例被称作所含对象。若两个状态均为空,或均为非空且其所含对象等价,则两个状态等价。
2) 非成员 any_cast
函数提供对所含对象的类型安全访问。
鼓励实现避免小对象的动态分配,但这种优化仅可以应用于 std::is_nothrow_move_constructible 对其返回 true
的类型。
成员函数
构造 any 对象(公开成员函数) | |
赋值 any 对象(公开成员函数) | |
销毁 any 对象(公开成员函数) | |
修改器 | |
更改所含对象,直接构造新对象 (公开成员函数) | |
销毁所含对象 (公开成员函数) | |
交换两个 any 对象(公开成员函数) | |
观察器 | |
检查对象是否含有值 (公开成员函数) | |
返回所含值的 typeid (公开成员函数) |
非成员函数
(C++17) | 特化 std::swap 算法 (函数) |
(C++17) | 对所含对象的类型安全访问 (函数模板) |
(C++17) | 创建 any 对象(函数模板) |
辅助类
(C++17) | 当类型不匹配时由按值返回形式的 any_cast 所抛出的异常(类) |
示例代码:
#include <any>
#include <complex>
#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
//https://zh.cppreference.com/w/cpp/utility/any
class Star
{
std::string name;
int id;
public:
Star(std::string name, int id) : name{ name }, id{ id }
{
std::cout << "Star::Star(string, int)\n";
}
void print() const
{
std::cout << "Star{\"" << name << "\" : " << id << "};\n";
}
};
int main()
{
std::cout << std::boolalpha;
// any 类型 any声明的变量可以修改变量的类型。 下面是int------> double------>bool
// type, any_case example
std::any a = 1;
std::cout << "a.type().name()=======" << a.type().name() << ": " << std::any_cast<int>(a) << '\n';
a = 3.14;
std::cout << "a.type().name()=======" << a.type().name() << ": " << std::any_cast<double>(a) << '\n';
a = true;
std::cout << "a.type().name()=======" << a.type().name() << ": " << std::any_cast<bool>(a) << '\n';
// 有误的转型 bad_any_cast example
try
{
//a = 3.1f; //这个是正确的float类型
a = 1;
std::cout << std::any_cast<float>(a) << '\n';
}
catch (const std::bad_any_cast& e)
{
std::cout << "e.what() ======" << e.what() << '\n';
}
// 拥有值 has_value example
a = 2;
if (a.has_value())
std::cout << "a.type().name()=======" << a.type().name() << ": " << std::any_cast<int>(a) << '\n';
// 重置后,a就已经没有值了 reset example
a.reset();
if (!a.has_value())
std::cout << "没有值\n";
// 指向所含数据的指针 a声明为整形
a = 3;
int* i = std::any_cast<int>(&a);
std::cout << *i << '\n';
//make_any example
auto a0 = std::make_any<std::string>("Hello, std::any!\n");
auto a1 = std::make_any<std::complex<double>>(0.1, 2.3);
std::cout << std::any_cast<std::string&>(a0);
std::cout << std::any_cast<std::complex<double>&>(a1) << '\n';
using lambda = std::function<void(void)>;
// 把 lambda 放入 std::any。尝试 #1(失败)。
std::any a2 = [] { std::cout << "Lambda #1.\n"; };
std::cout << "a2.type() = \"" << a2.type().name() << "\"\n";
// any_cast 转型到 <void(void)> 但实际类型不是
// std::function ……,而是 ~ main::{lambda()#1},且它对
// 每个 lambda 唯一。所以这会抛出……
try
{
std::any_cast<lambda>(a2)();
}
catch (std::bad_any_cast const& ex)
{
std::cout << ex.what() << '\n';
}
// 将 lambda 放入 std::any 中。尝试 #2(成功)
auto a3 = std::make_any<lambda>([] { std::cout << "Lambda #2.\n"; });
std::cout << "a3.type() = \"" << a3.type().name() << "\"\n";
std::any_cast<lambda>(a3)();
//emplace example
std::any celestial;
// (1) emplace( Args&&... args );
celestial.emplace<Star>("Procyon", 2943);
const auto* star = std::any_cast<Star>(&celestial);
star->print();
std::any av;
// (2) emplace( std::initializer_list<U> il, Args&&... args );
av.emplace<std::vector<char>>({ 'C', '+', '+', '1', '7' } /* 无参数 */);
std::cout << av.type().name() << '\n';
const auto* va = std::any_cast<std::vector<char>>(&av);
std::for_each(va->cbegin(), va->cend(), [](char const& c) { std::cout << c; }); //#include <algorithm>
std::cout << '\n';
//swap example
std::any a5 = 5;
std::any a6 = 6.3;
std::cout << "a5.type().name()=======" << a5.type().name() << ": " << std::any_cast<int>(a5) << '\n';
std::cout << "a6.type().name()=======" << a6.type().name() << ": " << std::any_cast<double>(a6) << '\n';
a5.swap(a6);
std::cout << "a5.type().name()=======" << a5.type().name() << ": " << std::any_cast<double>(a5) << '\n';
std::cout << "a6.type().name()=======" << a6.type().name() << ": " << std::any_cast<int>(a6) << '\n';
}
运行结果:
参考: