-1

In a project of mine, I have a header file with the following code:

#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

This file compiles fine with GCC on Linux. On Windows, however, this happens (lines broken for readability:

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 

Two things are happening here:

  1. The C++14 code is being executed, and
  2. MSVC fails to locate <experimental/optional>

Now, given (1.), I don't understand how (2.) can happen. If MSVC is in C++14 mode, the experimental headers for C++14 should be available. So what's going on? And how can I get MSVC to successfully compile my program ?

Notes:

  • This is a GitHub action runner VM, so I assume it's not a machine configuration problem.
  • Non-experimental C++ headers are found by the compiler
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • Yes that version defaults to C++14-ish (read the docs, it's more complicated than that), yes you can fix it and should set your standard via the [`/std`](https://learn.microsoft.com/en-us/cpp/build/reference/std-specify-language-standard-version?view=msvc-170) flag. The C++14 is also `/permissive` (note the lack of a minus)! which is very non standards compliant! So you should also set `/permissive-` too – Mgetz Apr 17 '23 at 20:05
  • @Mgetz: Ok, but - if it's C++14, why is (2.) happening? – einpoklum Apr 17 '23 at 21:21
  • 1
    C++14 is [the default](https://learn.microsoft.com/en-us/cpp/build/reference/std-specify-language-standard-version?view=msvc-170&viewFallbackFrom=vs-2019#remarks). The `optional` header is not experimental in VS2019, it supports C++17. – Hans Passant Apr 17 '23 at 21:38
  • @HansPassant: The experimental header is part of the definition of C++14. Are you saying that because MSVC support C++17 it dropped all of the C++14 headers which moved out of experimental? – einpoklum Apr 18 '23 at 07:26
  • @einpoklum IIRC anything in `experimental` is unstandardized and may not be there. I'm looking at the draft right now and not seeing anything to indicate they are required. AFAIK an experimental header is part of TR/TS and thus explicitly non-standard – Mgetz Apr 18 '23 at 13:36
  • Does this answer your question? [Are the experimental features of modern C++ reliable for long-term projects?](https://stackoverflow.com/questions/43318493/are-the-experimental-features-of-modern-c-reliable-for-long-term-projects) – Mgetz Apr 18 '23 at 13:36
  • @Mgetz: Not unless you know to tell me that MSVC doesn't have the experimental/filesystem header. – einpoklum Apr 18 '23 at 14:49
  • @einpoklum https://stackoverflow.com/q/62256738 It appears that Yes in the latest versions of their libraries they are not shipping it: https://stackoverflow.com/q/59564671 – Mgetz Apr 18 '23 at 15:36
  • @Mgetz: The first link only says that won't work if you're compiling C++17; it doesn't say that that's also the case with you'r compiling C++14. But the second link seems to be the answer. – einpoklum Apr 18 '23 at 16:21

1 Answers1

0

It seems the Microsoft has removed this header: Unlike libstc++ and libc++, which continue to make this header available (at least when compiling C++14), Microsoft decided not to do so. Apparently, that is within their right as far as the standard is concerned - although it's a really bad idea compatibility-wise.

What you could do is try to include <filesystem>, but condition on the version of MSVC being one in which that's available.

Thanks goes to @MGetz for helping me figure this out.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • A good solution would be to create an `experimental/filesystem` file in your code, containing `#include `. Since your main `#include ` uses angle brackets, it will find a compiler-provided version first, and only if that is not found, locate the one in the local source directory. – Ben Voigt Apr 18 '23 at 18:13
  • @BenVoigt: You mean, including `"experimental/filesystem"` instead of ``? – einpoklum Apr 18 '23 at 22:16
  • No, you want the search order associated with angle brackets (toolchain-provided headers first) – Ben Voigt Apr 19 '23 at 14:40