-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optionally use the standard library module #2575
Comments
A very recent check in, I believe this one, 291c502 broke the C++ 20 and above build in Visual Studio. It would be a good idea to add a VS 2022 C++20 build to CI, I would help to do this but know nothing about how that magic works! |
I see I never got back to this. Thanks for the (significant) effort put into the linked PR, but I am not interested in maintaining the results to support buggy prototype of modules inside MSVC. |
Hi @horenmar, Regarding this:
The only real bug in MSVC is being slightly to permissive when it comes to declarations in the global module, which should still retain all of the throughput benefit of C++ modules. I am also curious where 'prototype' came from? The modules implementation is far from a prototype, it adheres to everything specified in the standard (modulo a few bugs). The problems solved by the PR above are indeed problems that GCC and Clang will hit once their support for C++ modules matures. Please consider taking a second look. |
@cdacamar I was under the impression that mixing |
Just to add it appears that Clang is also going to have problems mixing |
I have linked this issue to https://arewemodulesyet.org/ so we can track modules support in the c++ eco system. |
Note https://arewemodulesyet.org/ is not a site about migrating to |
Recently Microsoft released their latest preview of VS which includes an implementation of the standard library modules std and std.compat. Other compilers/standard libraries will presumably follow suit, probably over the next year or so is my guess.
This feature request is to try to build catch2 using this standard library, and as a side effect allow users who are using the standard library module in their code to use catch2 headers. There are also benefits internally to catch itself, such as enforced code hygiene.
The goals
std
versusstd.module
and why the current code can’t be used by consumersimport <string>
Past experience
The following methodology is based on migrating a fairly large, ~100K LOC private code base and also the type_safe library at https://github.com/foonathan/type_safe. I would be extremely grateful if people suggest a better way, of improvements to this way of doing this, even if Catch rejects doing this at all. I will post a PR soon with the changes as proposed here so people can take a look or even try it out, my fork is https://github.com/davidhunter22/Catch2/tree/std_module.
What code changes
<string>
andimport std;
insteadstrncmp
tostd::strncmp
. Note that this can de done selectively so it is possible to#include <stdint.h>
instead. In practice the current code base is already fairly clean so there are not that many changes. Note using#include <stdint.h>
is less tragic in an implementation file rather than a public header file.<cassert>
asserts are macros. Ideally the code would never assert in header files via inline implementations, however catch does do this sometimes. My view is that implementations that assert should never be inline but I'm a pedant!<version>
feature test macros are also macros.<cerrno>
errno
is a macro<stdio.h>
There are a number of functions likeprintf_s
andgmtime_s
. These are defined in Annex K of the C standard, https://open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm. They are explicity excluded from the std namespace and therefore not in thestd
moduleDBL_MAX_10_EXP
,EOF
. I left these and included the relevant standard library header.The implementation in practice
The code is being built be generating a VS solution using the following command
The code has to be built with VS 2022, 17.5 Preview 1 or above, this is the firt version that supplies the
std
module,The code base after the changes has optional code based on a single macro. The code, mostly the sections that do
#include …
are changed to look like the followingThis change effects almost every file. If Catch had a central header that ervy other header include the
import std;
could be done ther but it does notThe only other change are some decorations of types so
uint32_t
becomesstd::uint32_t
. There are very few of these, maybe 10 or so.The
CATCH_USE_STDLIB_MODULE
macro is defined as follows.The root CMakeList.txt text has the following added
This result in a macro being defined in the Catch2 project's CMakeLists.txt.
The
CATCH_USE_STDLIB_MODULE
can be used by end users via the magic of CMake of manually if they want to use the std module version.The Catch2 project's CMakeLists.txt also enforces C++23 usage as that is the minium require the the
std
moduleWhy use the
std
module rather thanstd.compat
Using
std
rather thanstd.compat
allows you to be selective about what types are in the global namespace. If you usestd.compat
you get a lot of the garbage in the global namespace that old style headers, I.E.<vector>
put there.Note
<vector>
may not directly put things in the global namespace but it does transitively, for instance it usessize_t
which comes from<cstddef>
which then includes<stddef.h>
etc… all with lots of fun macros being defined along the way.Using
std.compat
at least controls the macro spam and avoids lots of internal types/functions/… being made visible. When using thestd
module, unlikestd.compat
you can choose to include certain headers, typically things likestdint.h
if you don't want to change code likeuint32_t
tostd::uint32_t
. The choice to pollute the global namespace is then very explicit.My view is that a library like Catch that is intended to be used by many consumers should try to minimize, as much as possible, the global/macro pollution that happens to users when they “#include <catch_....>
. Also as its name suggests
std.compatis a compatibility bridge, if it’s not much harder to do so why not go straight to
std`Why doesn't it all just work now
Why macro guard headers and do other changes shouldn't it all just work as is?
If a consumer does an
import std;
in theory using catch2 as is should just work but as STL, of MS fame, mentions here microsoft/STL#3195 in a discussion about thisCurrently when consumers of catch2 try to
import std
and then#include <catch_foo.h>
they will get compiler errors because the#include catch_....h
header will do things like#include <string>
. I suspect mixing old style headers with standard library modules will be a source of bugs for many years so why not avoid the issue. Note that not all headers trigger an error<cstdint>
does not while<cmath>
does. In general my feeling is if you doimport std;
then use headers like<stdint.h>
rather than<cstdint>
if you want global namespace “C” thing likesprintf
. You will already have thestd::sprintf
version via the module so why confuse the issue.MS compiler issue with the global namespace
The Microsoft compiler has an issue where it will sometimes, under conditions that are not at all obvious, make some std namespace types visible in the global namespace without any using statements or declarations. See here https://developercommunity.visualstudio.com/t/Possible-bug-in-VS-2022-175-Previews-1/10203863 for a discussion.
So the following code compiles
On discord Cameron DaCamara, a Microsoft compiler dev, said that this is a compiler issue to do with modules. He commented
So, this problem is unlikely to go away any time soon. This problem is actually not that bad, it just brings types like
std::uint8_t
into the global namespace. However, these types were already in the global namespace before via headers like . Using old style standard library headers it was pretty much impossible to avoid global namespace pollution. This compiler problem just means it is not always possible to clean up the usage of these global namespace types if that is even desired. When I say clean up, I mean the compiler should give you an error when you use a global type like::uint8_t
which you can then fix, this issue just mean that won’t always happen.The text was updated successfully, but these errors were encountered: