使用openMVS库,在VS2022中启用c++17标准编译仍然报错

使用openMVS库,在VS2022中启用c++17标准编译仍然报错

现象

项目中引用了某些开源库(例如openmvs2.1.0),编译时要求启用编译器对c++17的支持。

没问题!大家都知道在下图所示的位置调整C++语言标准:

但是,打开开关之后编译,依然报错:

这可真是一个令人百思不得其解的错误啊。报错的文件是官方的头文件type_traits,双击之后跳转的错误位置也看不出个所以然。

这下头大了。不过,之前编译openmvs库时,用的是同一版本的VS编译器,怎么就成功了呢?于是查看vcpkg自动编译openmvs时用cmake配置生成的CMakeCache.txt中的编译选项,才找到了真正原因,如下图所示:

图中标出来的选项是cmake生成的,并不常见,至少在VS2022中没有提供开关,而只能靠用户手动输入到属性页、C/C++、命令行的其他选项框中。

报错原因:__cplusplus

__cplusplus宏是MSVC编译器预定义的宏,它的值是许多语法特性的开关。前面讲了,要启用c++17标准,就在C++语言标准设置好即可。然而,__cplusplus宏值不随上面的C++语言标准/std 选项)设置而改变,需要同时添加:/Zc:__cplusplus编译选项,才能随着语言标准而改变,如下表所示:

/Zc:__cplusplus 选项 /std 选项 __cplusplus 值
Zc:__cplusplus /std:c++14(默认值) 201402L
Zc:__cplusplus /std:c++17 201703L
Zc:__cplusplus /std:c++20 202002L
Zc:__cplusplus /std:c++latest 当前最新日期,目前是202002L
Zc:__cplusplus-(已禁用) 任何值 199711L
未指定 任何值 199711L

表中的/std 选项就是上一节的C++语言标准属性。

可见,如果没有添加/Zc:__cplusplus__cplusplus宏的值始终都是199711L,启用的c++17标准也是不完整的。微软这么操作的理由是:有很多老代码写得不规范(不符合语言标准),之前版本的编译器(由于对语言标准的遵守不严格)能编译通过,我们希望使用新编译器时它们的改动也尽可能小。

于是,本来支持严格的标准C++语法的编译器的默认状态仍和原来一样,__cplusplus宏的值始终是199711L;直到开发者在编译器的命令行中加入/Zc:__cplusplus,它才真正变成实际使用语言标准的值。

其实多数情况下,__cplusplus宏的值对代码编译影响不大。但是很多高水平开源库使用了新语法,恰恰需要__cplusplus宏的值符合语言标准(/std 选项)才能编译通过,这是对开源开发者很不友好的。

P.S. 官方的愿景是,有朝一日仅需要设定/std 选项__cplusplus宏的值就随之改变,不需要额外添加/Zc:__cplusplus

解决方法

属性页---C/C++---命令行---其他选项中添加:/Zc:__cplusplus。重新编译,即可。

扩展阅读

/Zc-cplusplus的微软官方说明
C++语言标准切换选项
官方:终于能正确设定__cplusplus值了

用/std选项确定c/c++语言标准
强制符合语法标准选项/permissive-

一点认识:MSVC的C/C++编译器默认情况下实现了当前标准和未来一些标准中的语法。当指定语言标准为默认的/std:c++14时,大部分新标准的语法将被禁用,但仍有一部分在引入/std选项之前就实现的新语法标准可用。

但指定/std:c++xx(xx>14)时,新实现的c++xx以后的语法将不可用。

相关推荐
星星火柴9361 分钟前
数据结构:链表 (C++实现)
数据结构·c++·笔记·链表
跨境卫士-小汪2 分钟前
关税核爆72小时!跨境矩阵防御战紧急打响
开发语言·php
褚翾澜6 分钟前
Bash语言的社区交流
开发语言·后端·golang
独好紫罗兰19 分钟前
洛谷题单3-P4956 [COCI 2017 2018 #6] Davor-python-流程图重构
开发语言·python·算法
ん贤20 分钟前
2024第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组
c语言·数据结构·c++·经验分享·笔记·算法·蓝桥杯
CHPCWWHSU32 分钟前
vulkanscenegraph显示倾斜模型(5.6)-vsg::RenderGraph的创建
开发语言·javascript·ecmascript
zym大哥大1 小时前
C++多线程函数介绍
c++
向宇it1 小时前
【零基础入门unity游戏开发——2D篇】SortingGroup(排序分组)组件
开发语言·unity·c#·游戏引擎·材质
旺代1 小时前
JavaScript日期对象
开发语言·javascript·ecmascript
nlog3n1 小时前
Java 桥接模式 详解
java·开发语言·桥接模式