C++ modules
C++ modules were introduced in C++20 as an alternative to header files. Header files exist since its C legacy of the 70's so this is quite a chance. The biggest carrot dangled in front of you is the promised improved build times with slow build times as one the main pain points in C++. This marketing advertising is debatable: I made a test project with modules vs header files and the header files project wasn't slower. It needs to use pre-compiled header which is a non standard feature but every serious compiler implements it.
There is fundamental problem with modules and that class definitions are not self contained anymore. I do not know all the module rules but it seems that classical headers defined in ixx (module interface unit) files are not included in a cpp file when the module is imported. The lack of pch in modules not only increases compilation time for the normal header includes but pch's often carried global macro definitions like the used Windows SDK version and the dreaded NOMINMAX define.
Still the bait was just too big to pass by so I tried it out for a small (i.e. about 50 cpp files) project which builds fine with headers. That task took multiple days and became an exercise in frustration. I have never seen so many ICE's (Internal Compiler Error) since the old days of Visual Studio 4.2.
The solution with classical headers uses a source and header file per class. We have conventions like to put forward declarations in a fwd file and global typedef's and constants in a types file. I mimicked this behavior by using a module partition ixx file for the class and a cpp for the implementation. The problems encountered in VS2022:
- modules messes up when you use a forward file. A class definition may end up in a class declaration under certain conditions resulting in a spam of compilation errors. One cause is if the fwd file was imported after a partition import. Workaround: don't use the fwd file or import the fwd file before any other module partition.
- modules have problems with DLL exported classes from classical headers. Workaroud: use e.g. 'export using ::Person;' in an ixx file. This did not always worked: sometimes it messed up the build.
- modules gave ICE when exported data is visible through headers of the global module fragment of an ixx file. No workaround is possible only to circumvent this situation.
- pointer to member function (in a header) complete confused the compiler resulting in failure to detect the type and pointer to member function. See below
export template <typename T, typename Id, Id (T::*Pmf)() const>
class TestContainer
{
public:
void f()
{
std::for_each(m_vec.begin(), m_vec.end(),
[] (const auto& rptr) { (rptr.get()->*Pmf)(); });
}
std::vector<std::shared_ptr<T>> m_vec;
};
The last one broke any progress but I found a workaround in the meantime. I assume this is a bug of VS2022 modules since the code is accepted by VS2022 in a header solution and also by Clang in compiler explorer.
Conclusion
Module support for VS2022 is just too buggy. Perhaps it works when all is modules but a mix of DLL libraries with classical headers and modules just doesn't work. I haven't tried VS2026 yet which may have solved many of these issues.
I appreciate that the C++ committee took the build times issue serious. However C and C++ live half a decade with headers. Headers allow parallelization of compilation of translation units. Instead of inventing a new revolutionary mechanism I wonder if the build times couldn't be tackled by changes in the header mechanism. For example remove some preprocess phases (which the C++ committee already did); make templates easier parser-able even if that would break code. Header files need to be re-parsed for every translation unit due to changing definitions and macro's but can't a smart build system detect the need for this? I suppose there is only a small minority of header files which use these macro and definition tricks to change header behavior. There is one major exception and that is debug and release builds but on Visual Studio these are distinct builds in distinct directories.
No comments:
Post a Comment