This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
[Moved to DR at the April, 2013 meeting.]
The use of noexcept specifiers can cause instantiation of classes and functions that are not actually needed in the program, just to be able to complete the declaration. The actual value of the expression in the noexcept-specification is only needed if the function is defined (i.e., instantiated) or called, so it would significantly reduce the number of instantiations (and avoid certain kinds of errors when the value is currently required before a class is complete) if exception-specifications were treated like default arguments and only instantiated when they are actually needed.
Proposed resolution (February, 2012):
Change 13.7 [temp.decls] paragraph 2 as follows:
For purposes of name lookup and instantiation, default arguments and exception-specifications of function templates and default arguments and exception-specifications of member functions of class templates are considered definitions; each default argument or exception-specification is a separate definition which is unrelated to the function template definition or to any other default arguments or exception-specifications.
Change 13.8 [temp.res] paragraph 11 as follows:
[Note: For purposes of name lookup, default arguments and exception-specifications of function templates and fdefault arguments and exception-specifications of member functions of class templates are considered definitions (14.5). —end note]
Add a new paragraph following 13.8.4.1 [temp.point] paragraph 2:
If a function template or member function of a class template is called in a way which uses the definition of a default argument of that function template or member function, the point of instantiation of the default argument is the point of instantiation of the function template or member function specialization.
For an exception-specification of a function template specialization or specialization of a member function of a class template, if the exception-specification is implicitly instantiated because it is needed by another template specialization and the context that requires it depends on a template parameter, the point of instantiation of the exception-specification is the point of instantiation of the specialization that requires it. Otherwise, the point of instantiation for such an exception-specification immediately follows the namespace scope declaration or definition that requires the exception-specification.
Change 13.9.2 [temp.inst] paragraph 1 as follows:
...The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions,ordefault arguments, or exception-specifications, of the class member functions, member classes...
Add a new paragraph following 13.9.2 [temp.inst] paragraph 13:
Each default argument is instantiated independently. [Example: ... —end example]
If the exception-specification of a specialization of a function template or member function of a class template has not yet been instantiated, but is needed (e.g., to instantiate the function definition, to evaluate a noexcept-expression (7.6.2.7 [expr.unary.noexcept]), or to compare against the exception-specification of another declaration), the dependent names are looked up, the semantic constraints are checked, and the instantiation of any template used in the exception-specification is done as if it were being done as part of instantiating the declaration of the specialization. An exception-specification is not instantiated in order to calculate the exception-specification of a defaulted function in a derived class until the exception-specification of the derived member function becomes necessary.
Change the note 13.10.3 [temp.deduct] paragraph 7 as follows:
...[Note: The equivalent substitution in exception specifications is done only when thefunctionexception-specification is instantiated, at which point a program is ill-formed if the substitution results in an invalid type or expression. —end note]
Add a new paragraph following 14.5 [except.spec] paragraph 15:
A deallocation function (6.7.5.5.3 [basic.stc.dynamic.deallocation]) with no explicit exception-specification is treated as if it were specified with noexcept(true).
The exception-specification of a function template specialization is not instantiated along with the function declaration; it is instantiated when needed (13.9.2 [temp.inst]). The exception-specification of an implicitly-declared special member function is also evaluated as needed. [Note: Therefore, an implicit declaration of a member function of a derived class does not require the exception-specification of a base member function to be instantiated. —end note]
Notes from the February, 2012 meeting:
There should be a specific definition of when an exception-specification is needed and must thus be instantiated.
Additional discussion (September, 2012):
Daveed Vandevoorde brought up two additional points. First, the rule should be crafted so that an example like the following is ill-formed:
template<class T> T f() noexcept(sizeof(T) < 4); int main() { decltype(f<void>()) *p; }
Even though the exception-specification is not needed here, it should be instantiated (because of the unevaluated reference to f) in order to catch the ill-formed sizeof(T).
In addition, the proposed change creates an asymmetry between class templates and ordinary classes:
struct S {
void f() noexcept(sizeof(g()) < 8); // Invalid forward reference.
static int g();
};
but
template<typename> struct X {
void f() noexcept(sizeof(g()) < 8); // Okay.
static int g();
};
If the proposed change is adopted, the rules for exception-specifications in ordinary classes should be revised to make the parallel usage well-formed.
Proposed resolution (October, 2012):
Change 6.4.7 [basic.scope.class] paragraph 1 #1 as follows:
The potential scope of a name declared in a class consists not only of the declarative region following the name's point of declaration, but also of all function bodies, default arguments, exception-specifications, and brace-or-equal-initializers of non-static data members in that class (including such things in nested classes).
Change 6.5.3 [basic.lookup.unqual] paragraph 7 as follows:
A name used in the definition of a class X outside of a member function body, default argument, exception-specification, brace-or-equal-initializer of a non-static data member, or nested class definition29 shall be declared in one of the following ways:...
Change 6.5.3 [basic.lookup.unqual] paragraph 8 as follows:
For the members of a class X, a name used in a member function body, in a default argument, in an exception-specification, in the brace-or-equal-initializer of a non-static data member (11.4 [class.mem]), or in the definition of a class member outside of the definition of X, following the member's declarator-id31 , shall be declared in one of the following ways:...
Change 11.4 [class.mem] paragraph 2 as follows:
A class is considered a completely-defined object type (6.8 [basic.types]) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
Change 13.7 [temp.decls] paragraph 2 as follows:
For purposes of name lookup and instantiation, default arguments and exception-specifications of function templates and default arguments and exception-specifications of member functions of class templates are considered definitions; each default argument or exception-specification is a separate definition which is unrelated to the function template definition or to any other default arguments or exception-specifications.
Change 13.8 [temp.res] paragraph 11 as follows:
[Note: For purposes of name lookup, default arguments and exception-specifications of function templates and default arguments and exception-specifications of member functions of class templates are considered definitions (13.7 [temp.decls]). —end note]
Add the following as a new paragraph after 13.8.4.1 [temp.point] paragraph 2:
If a function template or member function of a class template is called in a way which uses the definition of a default argument of that function template or member function, the point of instantiation of the default argument is the point of instantiation of the function template or member function specialization.
For an exception-specification of a function template specialization or specialization of a member function of a class template, if the exception-specification is implicitly instantiated because it is needed by another template specialization and the context that requires it depends on a template parameter, the point of instantiation of the exception-specification is the point of instantiation of the specialization that requires it. Otherwise, the point of instantiation for such an exception-specification immediately follows the namespace scope declaration or definition that requires the exception-specification.
Change 13.9.2 [temp.inst] paragraph 1 as follows:
Unless a class template specialization has been explicitly instantiated (13.9.3 [temp.explicit]) or explicitly specialized (13.9.4 [temp.expl.spec]), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions,ordefault arguments, or exception-specifications of the class member functions, member classes, scoped member enumerations, static data members and member templates; and it causes the implicit instantiation of the definitions of unscoped member enumerations and member anonymous unions. However, for the purpose...
Insert the following as a new paragraph immediately preceding 13.9.2 [temp.inst] paragraph 14:
The exception-specification of a function template specialization is not instantiated along with the function declaration; it is instantiated when needed (14.5 [except.spec]). If such an exception-specification is needed but has not yet been instantiated, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the exception-specification is done as if it were being done as part of instantiating the declaration of the specialization at that point.
[Note: 13.8.4.1 [temp.point] defines the point of instantiation of a template specialization. —end note]
Change 13.10.3 [temp.deduct] paragraph 7 as follows:
The substitution occurs in all types and expressions that are used in the function type and in template parameter declarations. The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions. [Note: The equivalent substitution in exception specifications is done only when thefunctionexception-specification is instantiated, at which point a program is ill-formed if the substitution results in an invalid type or expression. —end note]
Change 14.5 [except.spec] paragraph 2 as follows:
...A type denoted in an exception-specification shall not denote an incomplete typeother than a class currently being defined. A type denoted in an exception-specification shall not denote a pointer or reference to an incomplete type, other than cv void*or a pointer or reference to a class currently being defined. A type cv T, “array of T”, or “function returning T” denoted in an exception-specification is adjusted to type T, “pointer to T”, or “pointer to function returning T” respectively.
Add the following as a new paragraph following 14.5 [except.spec] paragraph 15:
A deallocation function (6.7.5.5.3 [basic.stc.dynamic.deallocation]) with no explicit exception-specification is treated as if it were specified with noexcept(true).
An exception-specification is considered to be needed when:
in an expression, the function is the unique lookup result or the selected member of a set of overloaded functions (6.5 [basic.lookup], 12.2 [over.match], 12.3 [over.over]);
the function is odr-used (6.3 [basic.def.odr]) or, if it appears in an unevaluated operand, would be odr-used if the expression were potentially-evaluated;
the exception-specification is compared to that of another declaration (e.g. an explicit specialization or an overriding virtual function);
the function is defined; or
the exception-specification is needed for a defaulted special member function that calls the function. [Note: A defaulted declaration does not require the exception-specification of a base member function to be evaluated until the implicit exception-specification of the derived function is needed, but an explicit exception-specification needs the implicit exception-specification to compare against. —end note]
The exception-specification of a defaulted special member function is evaluated as described above only when needed; similarly, the exception-specification of a specialization of a function template or member function of a class template is instantiated only when needed.
[Note: this resolution reverses the decision in issue 1308.]