为什么 MSVC 尝试将我的代码编译为 C++14 却失败了?

Why is MSVC trying, and failing, to compile my code as C++14?

提问人:einpoklum 提问时间:4/18/2023 最后编辑:einpoklum 更新时间:4/19/2023 访问量:115

问:

在我的一个项目中,我有一个头文件,其中包含以下代码:

#if __cplusplus >= 201703L
#include <optional>
#include <any>
namespace foo {
using ::std::optional;
using ::std::nullopt;
} // namespace foo
#elif __cplusplus >= 201402L
#include <experimental/optional>
#include <experimental/any>
namespace foo {
using ::std::experimental::optional;
using ::std::experimental::nullopt;
} // namespace foo
#else
// define an optional class myself
// etc. etc.
#endif

此文件可在 Linux 上使用 GCC 正常编译。但是,在 Windows 上,会发生这种情况(为了便于阅读而断开行:

C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\bin\HostX64\x64\CL.exe 
/c /I"D:\a\libfoo\libfoo\src" 
/nologo /W4 /WX- /diagnostics:column /O2 /Ob2 /D _MBCS /D WIN32 /D _WINDOWS /D NDEBUG 
/D _CRT_SECURE_NO_DEPRECATE /D _CRT_SECURE_NO_WARNINGS 
/D _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING /D "CMAKE_INTDIR=\"Release\"" 
/Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"prog.dir\Release\\" 
/Fd"prog.dir\Release\vc142.pdb" /external:W0 /Gd /TP /errorReport:queue  
/Zc:__cplusplus "D:\a\libfoo\libfoo\prog\prog.cpp"
2023-04-17T19:12:53.5199300Z   prog.cpp
2023-04-17T19:12:53.6223921Z D:\a\libfoo\libfoo\src\foo\detail/optional.hpp(20,10):
fatal error C1083: Cannot open include file: 'experimental/optional': No such file or directory 

这里正在发生两件事:

  1. 正在执行 C++14 代码,并且
  2. MSVC 无法定位<experimental/optional>

现在,鉴于(1.),我不明白(2.)是如何发生的。如果 MSVC 处于 C++14 模式,则 C++14 的实验标头应可用。所以 这是怎么回事?我怎样才能让 MSVC 成功编译我的程序?

笔记:

  • 这是一个 GitHub 操作运行程序 VM,因此我认为这不是计算机配置问题。
  • 编译器会找到非实验性的 C++ 标头
visual-c++ github-actions visual-studio-2019 c++-standard-library std可选

评论

0赞 Mgetz 4/18/2023
是的,该版本默认为 C++-ish(阅读文档,它比这更复杂),是的,您可以修复它,并且应该通过 /std 标志设置您的标准。C++14也是(注意缺少减号)!这是非常不符合标准的!所以你也应该设置/permissive/permissive-
0赞 einpoklum 4/18/2023
@Mgetz:好的,但是 - 如果是 C++14,为什么会发生 (2.) ?
1赞 Hans Passant 4/18/2023
C++ 14 是默认值。该标头在 VS2019 中不是实验性的,它支持 C++17。optional
0赞 einpoklum 4/18/2023
@HansPassant:实验标头是 C++14 定义的一部分。你是说因为 MSVC 支持 C++17,它删除了所有从实验中移出的 C++14 标头?
0赞 Mgetz 4/18/2023
@einpoklum IIRC 中,任何内容都是非标准化的,可能不存在。我现在正在查看草案,没有看到任何迹象表明它们是必需的。AFAIK 是一个实验性标头,是 TR/TS 的一部分,因此显然是非标准的experimental

答:

0赞 einpoklum 4/19/2023 #1

似乎Microsoft已经删除了这个标头:与libstc++和libc++不同,libstc+和libc++继续使这个标头可用(至少在编译C++14时),Microsoft决定不这样做。显然,就标准而言,这是他们的权利 - 尽管在兼容性方面这是一个非常糟糕的主意。

您可以做的是尝试包含 ,但条件是 MSVC 的版本是可用的版本。<filesystem>

感谢@MGetz帮助我解决这个问题。

评论

0赞 Ben Voigt 4/19/2023
一个好的解决方案是在代码中创建一个文件,其中包含 .由于您的 main 使用尖括号,因此它将首先找到编译器提供的版本,只有在找不到该版本时,才在本地源目录中找到该版本。experimental/filesystem#include <filesystem>#include <experimental/filesystem>
0赞 einpoklum 4/19/2023
@BenVoigt:你的意思是,包括而不是?"experimental/filesystem"<experimental/filesystem>
0赞 Ben Voigt 4/19/2023
否,您需要与尖括号关联的搜索顺序(首先是工具链提供的标题)