1. Effects of This Paper
C++23 | P3422 | This paper |
---|---|---|
|
|
|
2. Motivation
There is a reasonable desire to define main as part of a module. The most often cited reason is to support unit testing of non-exported entities of a module.
2.1. Testing Modules
To be able to test non-exported entities of a module the test function must be a member of that module. One possible way to do this would be similar to the following:
module M ; extern "C++" int main () { // test non-exported entities in M here. }
Here the TU containing this is an implementation unit and does not need to be part of every program using
. However,
today this is ill-formed.
3. Why not P3422?
The way P3422 solves this problem is to implicitly attach
defined in the purview of a named module to the global
module instead. This does solve the problem, but it has two downsides.
3.1. Modular main ()
[P1203R0] - Modular main() is a paper that was presented in 2018 that proposed allowing
to be
attached to a module, thus allowing one per module. The idea was that this would allow having an implemenation defined
way to select which main is invoked when a program has these, like many other modern languages. This was also motiviated
by the same reasons as P3422.
There was reasonble interest at the time in EWGI that modular main in some form was something they were interested in pursuing. The authors of P1203 are no longer pursuing this paper, but P3422 would largely block off this path.
P3422 does discuss P1203, but this is mostly around one way to select a
. Other languages allow specifcially
selecting which entry point to use by name, such as
, which does not have the problems mentioned in the paper.
This paper does not propose modular main, just that we should keep that space open.
3.2. More Special Cases For main
In C++23 the idiomatic way to attach a declaration in a module to the global module is to use
. This was
specifically added to modules to provide a way to move declarations into a module without breaking ABI. This is exactly
what we want to do here with
.
Today having a linkage declaration on
is ill-formed, and has been since C++98. However, the primary reason this
was prohibited is that it really had no meaning, as the linkage of
for ABI purposes is defined by the platform,
and can’t be changed. Now that
has another meaning, I believe that it’s fine to apply this to
.
Implementations will still use whatever ABI is required by the platform, but will also attach it to the global module.
Making this change removes a special case from
, and avoids adding another special case. This makes the language
more consistent.
4. Allowing Language Linkage on main
Currently the linkage of main is implemenation-defined and the language linkage is C++ (because the default langauge linkage of all functions is C++). This paper does not change that, it just allows restating that the langauge linkage is C++.
A language linkage specification does also add
to the declaration; however, this is already allowed and is
ignored because [basic.start.main]/3 says that the linkage is implemenation-defined.
I do not believe there is any specification issue with allowing
, and there is no implemenation issue.
Clang and GCC already allow linkage specifcations on
with a warning even under
.
5. Compatibility
From the standard’s perspective this paper just makes previously ill-formed code well-formed.
In Clang and GCC this will just remove a warning as they already do the right thing. Implemenations should make
without
ill-formed, as the standard currently requires.
6. Wording
Modify [basic.start.main]/3 as follows:
The functionshall not be named by an expression. The linkage ([basic.link]) of
main is implementation-defined. A program that defines
main as deleted or that declares
main to be
main ,
inline ,
static , or
constexpr is ill-formed. The function
consteval shall not be a coroutine ([dcl.fct.def.coroutine]). The
main function shall not be declared with a linkage-specification ([dcl.link]) other than "C++" . A program that declares
main
a variable
that belongs to the global scope, or
main a function main that belongs to the global scope and is attached to a named module, or
a function template main that belongs to the global scope, or
an entity named main with C language linkage (in any namespace)
is ill-formed. The name
is not otherwise reserved.
main [Example 1: Member functions, classes, and enumerations can be called main, as can entities in other namespaces. — end example]