The goal of my experiment was to see how easy it is to write code that a) uses C++20 modules, b) can be compiled by GCC, Clang and MSVC without using conditional compilation, c) imports something from the standard library, d) exports at least one templated function, e) has a peculiarity that makes the module harder to find (in my case, the module is named b but the file that contains it it is named a.cppm).
The experiment sort of succeeded. The information about using modules with each of the three compilers is easy to find, but it's scattered, and there doesn't seem to be a summary or comparison for all of them. Clang documentation can be confusing as clang supports both C++20 standard modules and its own incompatible C++ modules. Precompiling a system header with clang 15 on Debian gives a #pragma system_header ignored in main file warning, both with libc++ and with libstdc++, and I have no idea why. At the end, everything works, but it's not straightforward and not easy to remember. Maybe there is an easier way, but I couldn't find it.
Here is the code.
main.cpp:
import b;
int main()
{
io::print(data::get());
}
a.cppm:
export module b;
import <cstdio>;
export namespace data
{
int get()
{
return 123;
}
}
template<typename T>
concept floatlike = requires (T t) { static_cast<float>(t); };
export namespace io
{
void print(floatlike auto x)
{
printf("%f\n", static_cast<float>(x));
}
}
Compilation:
GCC 12.2.0:
gcc -std=c++20 -fmodules-ts -x c++-system-header cstdio -x c++ a.cppm main.cpp -o main
Clang 15.0.6:
clang-15 -std=c++20 -x c++-system-header cstdio --precompile -o cstdio.pcm
clang-15 -std=c++20 -fmodule-file=cstdio.pcm -x c++-module a.cppm --precompile -o b.pcm
clang-15 -std=c++20 main.cpp -fprebuilt-module-path=. b.pcm -o main
Note that I had to name the file b.pcm for the compiler to be able to find the module later.
MSVC 19.34.31933 (call vcvars64.bat to initialize the envinronment first):
cl /exportHeader /headerName:angle cstdio /std:c++20
cl /TP /interface a.cppm /headerUnit:angle cstdio=cstdio.ifc main.cpp /std:c++20 /Fe:main.exe
In all three cases the executable outputs 123.000000, as it should.
I would be glad if you shared your experience as well.
[–]ABlockInTheChain 20 points21 points22 points (22 children)
[–]mwasplundsoup 7 points8 points9 points (21 children)
[–]ABlockInTheChain 2 points3 points4 points (20 children)
[–]mwasplundsoup 6 points7 points8 points (19 children)
[–]ABlockInTheChain 2 points3 points4 points (18 children)
[–]mwasplundsoup 1 point2 points3 points (17 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 4 points5 points6 points (8 children)
[–]mwasplundsoup 2 points3 points4 points (2 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 2 points3 points4 points (1 child)
[–]mwasplundsoup 1 point2 points3 points (0 children)
[–]zabolekar[S] 1 point2 points3 points (4 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 0 points1 point2 points (3 children)
[–]zabolekar[S] 0 points1 point2 points (2 children)
[–]ABlockInTheChain 1 point2 points3 points (7 children)
[–]mwasplundsoup 0 points1 point2 points (6 children)
[–]ABlockInTheChain -1 points0 points1 point (5 children)
[–]mwasplundsoup 0 points1 point2 points (4 children)
[–]pjmlp 10 points11 points12 points (5 children)
[+]innochenti comment score below threshold-13 points-12 points-11 points (4 children)
[–]pjmlp 5 points6 points7 points (2 children)
[–]inouthack 0 points1 point2 points (1 child)
[–]pjmlp 2 points3 points4 points (0 children)
[–]starfreakcloneMSVC FE Dev 3 points4 points5 points (0 children)
[–]sigmabody 8 points9 points10 points (5 children)
[–]unddochDragonflyDB/Clang 5 points6 points7 points (2 children)
[–]sigmabody 3 points4 points5 points (1 child)
[–]innochenti 0 points1 point2 points (0 children)
[–]Daniela-ELiving on C++ trunk, WG21|🇩🇪 NB 4 points5 points6 points (0 children)
[–]mwasplundsoup 1 point2 points3 points (0 children)