CWG Issue 1330 (original) (raw)

This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 118e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2025-11-05


1330. Delayed instantiation of noexcept specifiers

Section: 13.10.3 [temp.deduct]Status: CD3Submitter: Jason MerrillDate: 2011-06-05

[Moved to DR at the April, 2013 meeting.]

See also issues 595 and287.

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-specification_s were treated like default arguments and only instantiated when they are actually needed.

Proposed resolution (February, 2012):

  1. Change 13.7 [temp.decls] paragraph 2 as follows:

For purposes of name lookup and instantiation, default argumentsand _exception-specification_s of function templates and default arguments and _exception-specification_sof 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-specification_s.

  1. Change 13.8 [temp.res] paragraph 11 as follows:

[Note: For purposes of name lookup, default arguments and_exception-specification_s of function templates and fdefault arguments and _exception-specification_s of member functions of class templates are considered definitions (14.5). —_end note_]

  1. 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_.

  1. 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, or default arguments, or_exception-specification_s, of the class member functions, member classes...

  1. 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.

  1. Change the note 13.10.3 [temp.deduct] paragraph 7 as follows:

...[Note: The equivalent substitution in exception specifications is done only when the function exception-specification is instantiated, at which point a program is ill-formed if the substitution results in an invalid type or expression. —_end note_]

  1. Add a new paragraph following 14.5 [except.spec] paragraph 15:

A deallocation function (6.8.6.5.3 [basic.stc.dynamic.deallocation]) with no explicit_exception-specification_ is treated as if it were specified withnoexcept(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 T f() noexcept(sizeof(T) < 4);

int main() { decltype(f()) *p; }

Even though the exception-specification is not needed here, it should be instantiated (because of the unevaluated reference tof) 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 struct X { void f() noexcept(sizeof(g()) < 8); // Okay. static int g(); };

If the proposed change is adopted, the rules for_exception-specification_s in ordinary classes should be revised to make the parallel usage well-formed.

Proposed resolution (October, 2012):

  1. 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-specification_s, and_brace-or-equal-initializer_s of non-static data members in that class (including such things in nested classes).

  1. 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:...

  1. 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-id_31 , shall be declared in one of the following ways:...

  1. Change 11.4 [class.mem] paragraph 2 as follows:

A class is considered a completely-defined object type (6.9 [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-specification_s, and_brace-or-equal-initializer_s for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class_member-specification.

  1. Change 13.7 [temp.decls] paragraph 2 as follows:

For purposes of name lookup and instantiation, default argumentsand _exception-specification_s of function templates and default arguments and _exception-specification_sof 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-specification_s.

  1. Change 13.8 [temp.res] paragraph 11 as follows:

[_Note:_ For purposes of name lookup, default arguments and_exception-specification_s of function templates and default arguments and _exception-specification_s of member functions of class templates are considered definitions (13.7 [temp.decls]). —_end note_]

  1. 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_.

  1. 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, or default arguments, or_exception-specification_s 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...

  1. 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_]

  1. 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 the function exception-specification is instantiated, at which point a program is ill-formed if the substitution results in an invalid type or expression. —_end note_]

  1. Change 14.5 [except.spec] paragraph 2 as follows:

...A type denoted in an exception-specification shall not denote an incomplete type other 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 returningT” denoted in an exception-specification is adjusted to type T, “pointer to T”, or “pointer to function returning T” respectively.

  1. Add the following as a new paragraph following 14.5 [except.spec] paragraph 15:

A deallocation function (6.8.6.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:

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 inissue 1308.]