Currently, classes can be declared and defined at block scope, but these classes and their member functions have no linkage, which prohibits their use as template arguments.
The idea behind this proposal is to make local classes fully-fledged citizens of the C++ type system, usable wherever a namespace-scope class could be used.
This would enable functors for use with standard algorithms to be written in the block in which they are used, rather than having to write them outside the current function, at namespace or class scope.
For local classes to have external linkage, we need a way in which they can be uniquely identified, so that classes or objects of the same name from a different scope do not cause name clashes.
To resolve this issue, I propose that each block scope that defines local classes be given a unique identifier, similar to the way that anonymous namespaces are given unique identifiers in different translation units. The local classes defined within each block scope are then made members of a namespace with this uniquely-identifying name. Since this name is compiler-generated and unique, there is thus no way of identifying a local class from outside its block. e.g.
is equivalent to
is equivalent to
It is essential that different overloads of the same function name yield different unique names for their enclosed scopes, and that different instantations or specializations of the same function template also yield different unique names, so that name lookup rules remain unchanged, and the One Definition Rule is not violated.
Variables declared at block scope may have static storage duration, in which case all references to that variable within the given scope
refer to the same instance of the variable, even if the function is declared
inline and used in multiple translation units. In
order to maintain this functionality, even when the static object has local-class-type, the algorithm for generating the
unique name must be such that the same names are generated for the same function definition in different translation
Consequently, the algorithm for generating the unique names must depend solely on the scope in which the current function definition lies, the name and signature of the enclosing function, any relevant template parameters, and the information available within the function definition. The precise details of the algorithm remain implementation defined.
Local classes can have member functions, which introduce block scopes, that may therefore have their own local classes, and so forth. All such classes should have external linkage, and be assigned appropriate unique names, just as if they were defined within a normal namespace-scope function.
No change is proposed to the language rules regarding forward declarations and out-of-line member definitions — both remain illegal for local classes.
The interaction of local classes with templates is a key part of this proposal. Firstly, if a local class is defined within a function template, or a member function of a class template, it is essential that every unique instantiation of the function yields a unique name for the local classes namespace.
Secondly, as local classes now have external linkage, it becomes possible to instantiate a template with a local class as a template parameter. If the same template is instantiated for different local classes of the same name, each instantiation should be unique. This effect can be correctly achieved by treating each local class as a member of its appropriate uniquely-named namespace, as above.
Currently, local classes are not permitted to have member templates. I see this as a needless restriction, now that local classes have external linkage.
Also, it may be desirable to specialize a template for a particular local class. This would have to be done within the block in which the local class is defined, as the class cannot be identified by name from outside that block. However, template declarationsare not permitted at block scope, so templates cannot be specialized for local classes without a further language change.
Finally, it may be desirable to define local templates. Again, this requires a further language change.
Currently, local classes are only permitted to have friends that have already been declared in another scope. Though this can be inconvenient, I see problems with lifting this restriction, such as what scope the friend class or function is a member of, if it is declared or defined within a local class definition.
Add a new paragraph between current paragraphs 7 and 8:
A name having local scope (3.3.2) has external linkage if it is the name of:
— a named class (clause 9), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes (7.1.3); or
— a named enumeration (7.2), or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes (7.1.3); or
— enumerator belonging to an enumeration with external linkage.
Change the current paragraph 8 (new paragraph 9) to remove references to local classes and enumerations:
Names not covered by these rules have no linkage. Moreover, except as noted, a name declared in a local scope (3.3.2) has no linkage. A name with no linkage shall not be used to declare an entity with linkage. If a declaration uses a typedef name, it is the linkage of the type name to which the typedef refers that is considered. This implies that names with no linkage cannot be used as template arguments (14.3).
Change the note in paragraph 3 to allow local class member functions to have linkage:
An inline member function (whether static or nonstatic) may also be defined outside of its class definition provided either its declaration in the class definition or its definition outside of the class definition declares the function as inline. [Note: both member functions of a class in namespace scope and member functions of a local class (9.8) have external linkage.]
Add a new paragraph after paragraph 4:
Local classes have external linkage (3.5). Each block that contains local class definitions is assigned a unique namespace name in the innermost namespace enclosing the function definition of which it is a member. This name shall depend only on the scope of which the function is a member, the function name and signature, and any relevant template parameters. Each local class defined within this block is considered to have been defined inside this uniquely-named namespace for linkage purposes. The same function definition will always generate the same unique namespace name, even in different translation units. (Note: This enables block-scope objects of static duration can refer to the same object, even if they have local-class type, and are defined in an inline function used in multiple translation units)
Remove the restriction on member-templates of local classes in paragraph 2:
Access control rules (clause 11) apply to member template names. A destructor shall not be a member template. A normal (non-template) member function with a given name and type and a member function template of the same name, which could be used to generate a specialization of the same type, can both be declared in a class. When both exist, a use of that name and type refers to the non-template member unless an explicit template argument list is supplied.