The C++20 standard introduced modules. This feature enhances the language by reducing reliance on header files. Visual Studio 2022’s Visual C++ projects have built-in support for modules. However, they don’t automatically provide access to modularized versions of the standard library headers. This article shows a quick way to configure Visual Studio 2022 to use C++ standard library modules.
For better or worse, current iterations of Visual Studio make it very difficult to change Visual C++ defaults. On the “worse” side, you have to repeat the same work for each new project. On the “better” side, when you share your projects via source control, you won’t need to supply a lot of configuration instructions. Anyone who opens your solution file with the accompanying vcxproj.* files will automatically use the same settings. This approach still has problems, of course. This article will not debate the viewpoints; it simply goes with the “better” argument and shows how to configure a project for C++ standard library modules.
To start, open the project’s properties. The project is in the
Solution Explorer
pane underneath the solution.
Right-click on the project and click the
Properties
entry. It’s all the way at the far end of the menu.
You should now see the Properties dialog for your solution. We will use it in the following two subsections.
Part 1: Set the Compiler to Use the C++20 Standard
The dialog box should have opened to the
General
sub-tab under the
Configuration Properties
root item. If not, switch to that location.
At this time, Visual Studio 2022 defaults to the C++14 standard. To use C++ modules, you need to switch to at least the C++20 standard. In the
C++ Language Standard
drop-down, click
ISO C++20 Standard (/std:c++20)
. Alternatively, choose a preview set (or even a later standard if available when you read this).
Adoption of C++ modules has been slow and will probably never replace traditional
include
and
define
preprocessor macros in older, larger projects. Even when you have modules available, you will uncover reasons to prefer to include a standard header. For a regular CPP file, like the one with your main routine, you can intersperse
include
with
import
as makes sense.
When you author a module, the rules are different. VC++ will complain about an
#include
line that appears after a module declaration line and if a module declaration line appears anywhere except the first line. Consider the following example code:
Microsoft Visual C++ complains about this with warning C5244: '#include ' in the purview of module 'MyModule' appears erroneous. Consider moving that directive before the module declaration, or replace the textual inclusion with 'import ;'.
If you move the include line above the module declaration, VC++ won’t like that either, although it does give a hint how to fix it: Warning C5201: a module declaration can appear only at the start of a translation unit unless a global module fragment is used.
To use includes in a module file without upsetting your compiler, start your module definition or implementation file like this:
module;
// includes and defines here
module MyModule;
// import lines and import export lines here
You can use this format in module declaration (usually .ixx or .cppm files) and implementation files. Basically, start the file with the line module;, enter includes, then write the rest of the module declaration/definition.
This layout comes in handy in those places where a module could work but the compiler generates warnings that you can’t correct and your environment does not tolerate compiler warnings.
Additional Notes
Modules don’t have nearly the same length of vetting and debugging history as header files. Expect some hiccups. As an example, when compiled with Visual Studio C++ 17.5, the demonstration program generates the following warning:
warning C5260: the constant variable 'std::memory_order const (* `std::memory_order __cdecl std::_Combine_cas_memory_orders(std::memory_order,std::memory_order)'::`2'::_Combined_memory_orders)[6]' has internal linkage in an included header file context, but external linkage in imported header unit context; consider declaring it 'inline' as well if it will be shared across translation units, or 'static' to express intent to use it local to this translation unit
You cannot do anything about this in the short term other than revert to using header files. Future updates to the compiler and toolset will include fixes as users find them and Microsoft corrects them.
Project Runspace distributes knowledge freely, but we also protect the hard work of our authors and content providers. We want you to use what you learn here for any otherwise legal and ethical purposes, which does not include content theft. The rule is simple: do not try to pass off anyone else's work as your own. If you want to copy a section or rephrase an idea that you found here and publish it, then you must cite it. The legalese is in the terms of the license.