C++ 17 std::any

C++ 17 std::any

std::any 可以保存任意类型的单个值。和 std::variant 不同,variant 的类型集合是在编译期固定好的,而 any 更灵活,但类型信息也更弱。

1. std::any 是干什么的?

它适合这种场景:

  • 你需要一个通用容器
  • 里面可能装不同类型的值
  • 但这些类型在编译期不一定能全部列出来

例如插件配置、扩展参数、弱类型数据通道等。

2. 基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <any>
#include <iostream>
#include <string>
using namespace std;

int main()
{
std::any data = 10;
cout << any_cast<int>(data) << endl;

data = string("hello");
cout << any_cast<string>(data) << endl;
return 0;
}

这里一个 std::any 先存 int,后面又改存 string,这是可以的。

3. 常用操作

3.1 赋值

1
2
std::any value = 42;
value = std::string("abc");

3.2 判空

1
2
if (value.has_value()) {
}

3.3 取值

1
cout << std::any_cast<int>(value) << endl;

如果类型不匹配,通常会抛出 std::bad_any_cast

4. 一个简单例子

1
2
3
4
5
6
7
8
9
10
11
12
#include <any>
#include <map>
#include <string>
using namespace std;

int main()
{
map<string, any> config;
config["port"] = 8080;
config["host"] = string("127.0.0.1");
config["debug"] = true;
}

像这种“配置项类型不统一”的场景,any 会比较自然。

5. 和 std::variant 的区别

variant

  • 候选类型固定
  • 类型安全更强
  • 更适合明确的类型集合

any

  • 类型更灵活
  • 运行时才能知道真实类型
  • 更适合开放式扩展场景

如果你已经知道只有 int/double/string 这几种类型,那通常 variant 更合适。
如果类型完全开放,那才更偏向 any

6. 使用时要注意的点

6.1 取值时必须知道原始类型

std::any 不会帮你自动转换类型。
存进去的是 int,取的时候也必须按 int 取。

6.2 类型不匹配会抛异常

所以在不确定真实类型时,要谨慎使用 any_cast

6.3 灵活是优点,也可能是缺点

any 太灵活时,接口约束会变弱。
如果一套系统里到处都是 std::any,后期维护会变得比较痛苦。

总结

std::any 适合处理“类型开放、接口不固定”的值传递场景。
它比 variant 自由,但也因此少了一层编译期约束。能用明确类型时最好还是明确类型,只有在确实需要动态类型容器的时候,再考虑 std::any