CMake设置C++20失效求助:g++9.4仍采用C++17
问题背景
为使用std::jthread库,将项目C++标准从17切换到20,在根目录CMakeLists.txt中添加:
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED YES)
但通过以下代码检测时,输出仍为C++17:
if (__cplusplus == 201703L) std::cout << "C++17\n"; else if (__cplusplus == 201402L) std::cout << "C++14\n"; else if (__cplusplus == 201103L) std::cout << "C++11\n"; else if (__cplusplus == 199711L) std::cout << "C++98\n"; else if (__cplusplus == 202002L) std::cout << "C++20\n"; else std::cout << "pre-standard C++\n";
使用编译器为g++(Ubuntu 9.4.0-1ubuntu1~20.04.1)9.4.0,该版本宣称支持C++20。
核心原因
1. CMake默认启用GNU扩展,传递的是-std=gnu++20而非-std=c++20
g++ 9.x中,当使用带GNU扩展的-std=gnu++20时,__cplusplus宏不会被设置为C20的标准值202002L,而是保持为C17的201703L以兼容旧代码。CMake的CMAKE_CXX_EXTENSIONS默认值为ON,会自动给g++传递-std=gnu++20参数。
2. 标准配置代码的位置错误
如果set(CMAKE_CXX_STANDARD 20)等配置是在add_executable/add_library之后才添加的,这些设置不会作用于已创建的编译目标,编译器仍会沿用之前的C++17标准。
额外注意:g++9.4对std::jthread的支持缺失
std::jthread是C20的新特性,但g直到10.x版本才完全实现该类,g9.4仅支持部分C20特性,即使解决了标准检测问题,也无法正常使用std::jthread。
解决办法
1. 关闭GNU扩展,强制使用纯C++20标准
在CMakeLists.txt中补充配置:
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS OFF) # 关键:禁用GNU扩展,让CMake传递-std=c++20
2. 调整配置代码的位置
确保上述标准配置代码放在add_executable或add_library命令之前,保证配置能覆盖到目标编译参数。
3. 验证编译参数
通过make VERBOSE=1(Makefile生成器)或ninja -v(Ninja生成器)查看实际编译命令,确认参数中包含-std=c++20而非-std=gnu++20。
4. 升级编译器(针对std::jthread需求)
若要使用std::jthread,需将g++升级到10.x或更高版本,比如在Ubuntu 20.04中可通过安装g++-10包实现。
内容的提问来源于stack exchange,提问作者Pedro Lopes

