问题引入
相同的代码,在ubuntu18不会报错,到ubuntu22就报错了。
用最小测试用例进行验证:
#include <iostream>
#include <vector>
#include <string>
// #include <map> 如果不包含map的话,也会打印optional缺失的报错
int main() {
std::optional<int> opt;
return 0;
}
验证发现在ubuntu18 map头文件会隐式包含optional头文件了;如果去掉map,一样会报错。
随着标准库更新,std库优化了头文件之间的依赖关系,减少不必要的间接包含,以提高编译速度和代码清晰度。 在 Ubuntu 22 的新版 libstdc++
中,<map>
不再间接包含 <optional>
,因此代码必须显式包含 <optional>
才能编译通过。
ubuntu系统的std版本
用下面这个命令可以看stdc++的版本:
strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX
虽然我们工程已经切换成clang编译了,但是std库还是用的GNU的,这是因为ubuntu系统还是使用GCC进行编译的,而且暂时没有切换到clang的计划。
dpkg -S /usr/lib/x86_64-linux-gnu/libstdc++.so.6
在ubuntu18,stdc++的版本为8.3.0,到ubuntu22,已经升级至12.3.0了
由于std基础库带来的差异挺麻烦的,一套代码需要兼容两个不同的std库。
目前看下来只能在ubuntu18上加一些限制,让大家强制加上optional头文件。