Visual Studio 2012 __cplusplus 和 C++ 11

22

有人知道为什么我的Visual Studio 2012 c++项目中__cplusplus被定义为199711L(这是“旧”的C++)吗?由于VS 2012现在支持C++ 11,它不应该说201103L吗?即使我包括了C++ 11头文件,它仍然被错误地定义。有什么线索吗?

5个回答

16

谢谢。我已经在错误报告中添加了自己的评论。 - user152949
1
现在是2014年,VS 2013已经发布,但似乎该标志仍然报告旧版本(请参阅上面链接中的讨论)。如果您在此处查看支持的功能,则甚至开始引入C++14:http://msdn.microsoft.com/en-us/library/hh567368.aspx-“ Visual C++ in Visual Studio 2013进一步扩展了这种覆盖范围,并且还支持一些选择的C++14库功能。”我真的不理解为什么每个人都可以选择要实现哪些功能。这将越来越破坏可移植性! - flohack
1
@flohack - 如果你看适当的技术讲座,你会发现在 VS 团队上实现不同特点负载... 好吧... 不同。有些事情很快,有些则不是。他们做了一些快速添加 make_unique 的库,因为它不需要时间。你还会知道 MS 正在开创标准化的几个方面,如 async/await 提案,并且他们也将其作为优先事项,以便我们拥有可工作的实现来完善我们的想法/提议。并不是说他们选择要实现什么,而是选择何时实现。 - Mark
1
马克,我同意。然而,我质疑标准组织的步伐。如果主要供应商在实施功能方面落后,然后可能下一个标准迭代已经在门口,那么这看起来并不像是一种有用的标准化策略,而更像是市场炒作工具。正如我在学校里学到的那样,标准应该帮助行业(和市场)使事物更具可比性,并防止供应商之间的不公平兼容性问题。如果出现这种情况,代码可移植性可能会受到严重影响。 - flohack

9

这实际上取决于您期望宏实际意义是什么。201103L是否意味着“该编译器在编译器和库中完全支持C++11?” 是否应该意味着“该编译器支持某些合理的C++11子集?” 是否应该意味着“该编译器以某种方式支持至少一个C++11特性?”

每个实现何时提升版本号都由其自己决定。Visual Studio不同于Clang和GCC,因为它没有单独的C++03编译模式;它提供了一组特定的功能,这就是它所提供的。

通常,单个宏不是决定何时使用某个功能的有用工具。 Boost.Config 是一种更可靠的机制。标准委员会正在研究如何解决这个问题在未来的标准版本中。


5
我同意Nicol的观点。检测__cplusplus >= 201103L 的唯一原因是为了检查您是否可以使用新功能。如果编译器仅实现了新功能的一半,但使用了__cplusplus的新值,则会在许多通过__cplusplus >= 201103L保护的有效C++11代码上编译失败(我有一些使用thread_local和*this引用的代码)。另一方面,如果它保持199711L,它将使用安全的C++98代码,这仍然是可以的。这样可能会错过一些优化,但您仍然可以使用其他方式检测特定功能是否可用(编译器版本,编译器特定宏,如__GXX_EXPERIMENTAL_CXX0X__,boost宏可以为您检查编译器宏等)。重要的是要有一个安全的默认值。
切换到__cplusplus的新值有两个可能的原因:
- 您的编译器完全支持C++11(或接近,总会有错误) - 这是您的编译器的实验模式,不应在生产中使用,并且通常缺少的功能视为错误。
据我所知,所有进行切换的编译器都属于第二类。
我相信一些编译器供应商对更改__cplusplus的值过于热衷(最容易实现的C++11功能,很好的宣传),而某些人则更为保守。

4
截至2018年4月,MSVC 2017现在可以正确报告宏,但仅当使用特定开关(/Zc:__cplusplus)时才能实现。这是因为许多旧代码依赖于检测MSVC编译器的宏的旧值。 来源 希望未来一旦全球人民更新了他们的代码,微软将默认正确报告该宏。

适用于 Visual Studio 2019 (您需要手动将 /Zc:__cplusplus 添加到项目命令行选项中)。如果您依赖于 __cplusplus,请添加命令行开关。如果您仅在 Windows 上使用 Visual Studio,则 _MSVC_LANG 宏可能更合适,因为它基于所选的 C++ 标准进行更改。由于有解决方法,Microsoft 不太可能妥协。 - AlainD

2
正如另一个回答所指出的那样,/Zc:__cplusplus 就是答案。假设您有一堆位于文件夹层次结构下的 .vcxproj 文件,只需将名为 Directory.Build.props 的文件放置到共同的父文件夹中,并填写如下内容:
<?xml version="1.0" encoding="utf-8"?>
<Project>
  <ItemDefinitionGroup>
    <ClCompile>
      <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
    </ClCompile>
  </ItemDefinitionGroup>
</Project>

您还可以使用自己的用户属性表来设置这个。例如,在所有的 Microsoft.Cpp.*.user.props 文件中(其中 * 是目标平台的占位符)位于 %LOCALAPPDATA%\Local\Microsoft\MSBuild\v4.0 中。
此外,在代码中采取防御性措施可能是明智的,这意味着需要像下面这样检查 _MSVC_LANG 和 __cplusplus 两者:
#if defined(__cplusplus) && defined(_MSVC_LANG) && (__cplusplus == 199711L)
// Check against _MSVC_LANG with the value you expect for __cplusplus
#else
// Check against __cplusplus as usual
#endif

我建议在你不能确定你的代码(例如,因为你是库的作者而)被使用时,每当在命令行上指定了/Zc:__cplusplus,就使用类似这样的东西。
我仍然有点困惑,为什么在VS2022中仍然是这种情况,因为如果你看一下C++编译器支持,Visual C++相比其他编译器并不差。
以上所说的,你可能想使用特性测试宏而不是测试C++标准版本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接