In VS 2022 17.13, MSVC is adding a /std:c++23preview
option to indicate C++23-in-progress, with /std:c++latest
changing to indicate C++26-in-progress. (This is because MSVC’s STL will be finishing the C++23 library-only features soon and will need to begin work on C++26 library-only features, even though MSVC’s compiler front-end C1XX still has many C++23 core language features to implement. In the C++20 era, the library and compiler reached completeness around the same time, which is why we need to alter the design now.) The intention is that when both MSVC’s STL and C1XX are C++23-complete, and we’re comfortable with locking down the ABI, we’ll add the final /std:c++23
option, and then deprecate /std:c++23preview
(and maybe remove it eventually).
As part of this work, we’re changing the values used for __cplusplus
(when in /Zc:__cplusplus
mode, which is still not the default) and _MSVC_LANG
. For C++23 we’re going to use the final Standard value 202302L
. For C++26 we’re going to use the placeholder value 202600L
.
We’d like clang-cl to begin understanding /std:c++23preview
. (I suppose you could accept /std:c++23
as a synonym immediately, that’s up to you. cl.exe
won’t be accepting that yet.) With how we’re changing the STL’s logic to detect the Standard mode (implemented in VCRuntime), it would be sufficient to make /std:c++23preview
a synonym for passing -std=c++23
to underlying Clang, but it would be better to also update the __cplusplus
and _MSVC_LANG
values accordingly.
Here’s a self-contained test case:
C:\Temp>type meow.cpp
#include <cstdio>
using namespace std;
// Reduced from VCRuntime's logic. We use the larger of _MSVC_LANG and __cplusplus:
#if defined(_MSVC_LANG) && _MSVC_LANG > __cplusplus
#define STL_LANG _MSVC_LANG
#else
#define STL_LANG __cplusplus
#endif
#if STL_LANG > 201402L
#define HAS_CXX17 1
#else
#define HAS_CXX17 0
#endif
#if STL_LANG > 201703L
#define HAS_CXX20 1
#else
#define HAS_CXX20 0
#endif
#if STL_LANG > 202002L
#define HAS_CXX23 1
#else
#define HAS_CXX23 0
#endif
#if STL_LANG > 202302L
#define HAS_CXX26 1
#else
#define HAS_CXX26 0
#endif
int main() {
#ifdef __clang__
printf("Clang");
#else
printf("C1XX");
#endif
printf("; __cplusplus: %ld; _MSVC_LANG: %ld; ", __cplusplus, _MSVC_LANG);
#if HAS_CXX26
printf("detected C++26\n");
#elif HAS_CXX23
printf("detected C++23\n");
#elif HAS_CXX20
printf("detected C++20\n");
#elif HAS_CXX17
printf("detected C++17\n");
#else
printf("detected C++14\n");
#endif
}
When built with my development version of MSVC where I’ve added the new option:
C:\Temp>cl /EHsc /nologo /W4 /std:c++14 meow.cpp && meow
meow.cpp
C1XX; __cplusplus: 199711; _MSVC_LANG: 201402; detected C++14
C:\Temp>cl /EHsc /nologo /W4 /std:c++17 meow.cpp && meow
meow.cpp
C1XX; __cplusplus: 199711; _MSVC_LANG: 201703; detected C++17
C:\Temp>cl /EHsc /nologo /W4 /std:c++20 meow.cpp && meow
meow.cpp
C1XX; __cplusplus: 199711; _MSVC_LANG: 202002; detected C++20
C:\Temp>cl /EHsc /nologo /W4 /std:c++23preview meow.cpp && meow
meow.cpp
C1XX; __cplusplus: 199711; _MSVC_LANG: 202302; detected C++23
C:\Temp>cl /EHsc /nologo /W4 /std:c++latest meow.cpp && meow
meow.cpp
C1XX; __cplusplus: 199711; _MSVC_LANG: 202600; detected C++26
(If the conforming /Zc:__cplusplus
mode were active, its value would match _MSVC_LANG
in every case.)
Here is Clang 18’s behavior, showing that -Xclang -std=c++23
would be sufficient, and that -Xclang -std=c++2c
behaves synonymously with /std:c++latest
:
C:\Temp>clang-cl /EHsc /nologo /W4 /std:c++14 meow.cpp && meow
Clang; __cplusplus: 201402; _MSVC_LANG: 201402; detected C++14
C:\Temp>clang-cl /EHsc /nologo /W4 /std:c++17 meow.cpp && meow
Clang; __cplusplus: 201703; _MSVC_LANG: 201703; detected C++17
C:\Temp>clang-cl /EHsc /nologo /W4 /std:c++20 meow.cpp && meow
Clang; __cplusplus: 202002; _MSVC_LANG: 202002; detected C++20
C:\Temp>clang-cl /EHsc /nologo /W4 -Xclang -std=c++23 meow.cpp && meow
Clang; __cplusplus: 202302; _MSVC_LANG: 202004; detected C++23
C:\Temp>clang-cl /EHsc /nologo /W4 -Xclang -std=c++2c meow.cpp && meow
Clang; __cplusplus: 202400; _MSVC_LANG: 202004; detected C++26
C:\Temp>clang-cl /EHsc /nologo /W4 /std:c++latest meow.cpp && meow
Clang; __cplusplus: 202400; _MSVC_LANG: 202004; detected C++26