Deducing noexcept-specifiers
Section [temp.deduct.type]
John Spicer

Created on 2017-09-06.00:00:00 last changed 3 months ago


Date: 2022-06-15.00:00:00

Proposed resolution (June, 2022):

  1. Change [temp.deduct.type] paragraph 3 as follows:

  2. A given type P can be composed from a number of other types, templates, and non-type values:

    • A function type includes the types of each of the function parameters and, the return type, and its exception specification.

    • ...

  3. Add the following to Example 3 in [temp.deduct.type] paragraph 7:

  4. Here is an example where two template arguments are deduced from a single function parameter/argument pair...

    Here is an example where the exception specification of a function type is deduced:

      template <bool E> void f1(void (*)() noexcept(E));
      template<bool> struct A { };
      template<bool B> void f2(void (*)(A<B>) noexcept(B));
      void g1();
      void g2() noexcept;
      void g3(A<true>);
      void h() {
        f1(g1);    // OK: E is false
        f1(g2);    // OK: E is true
        f2(g3);    // error: B deduced as both true and false

    Here is an example where a qualification conversion applies...

  5. Change [temp.deduct.type] paragraph 8 as follows:

  6. A template type argument T, a template template argument TT, or a template non-type argument i can be deduced if P and A have one of the following forms:
      cvopt T
      Topt[integer-constant iopt]
      template-name<T> (where template-name refers to a class template)
      Topt(Topt) noexcept(iopt)
      T type::*
      type T::*
      Topt Topt::*
      T (type::*)()
      type (T::*)()
      type (type::*)(T)
      type (T::*)(T)
      T (type::*)(T)
      T (T::*)()
      T (T::*)(T)
      template-name<i> (where template-name refers to a class template)

    where (T) represents a parameter-type-list ( [dcl.fct]) where at least one parameter type contains a T, and () represents a parameter-type-list where no parameter type contains a T.

    • Topt represents a type or parameter-type-list that either satisfies these rules recursively, is a non-deduced context in P or A, or is the same non-dependent type in P and A,

    • TTopt represents either a class template or a template template parameter,

    • iopt represents an expression that either is an i, is value-dependent in P or A, or has the same constant value in P and A, and

    • noexcept(iopt) represents an exception specification (14.5 [except.spec]) in which the (possibly-implicit, see [dcl.fct]) noexcept-specifier's operand satisfies the rules for an iopt above.

    [Note: If a type matches such a form but contains no Ts, is, or TTs, deduction is not possible. —end note]

    Similarly, <T> represents template argument lists where at least one argument contains a T, <i> represents template argument lists where at least one argument contains an i and <> represents template argument lists where no argument contains a T or an i.

  7. Add the following as a new paragraph following [temp.deduct.type] paragraph 14:

  8. The type of N in the type T[N] is std::size_t. [Example 9: ... —end example]

    The type of B in the noexcept-specifier noexcept(B) of a function type is bool.

      template<bool> struct A { };
      template<auto> struct B;
      template<auto X, void (*F)() noexcept(X)> struct B<F> {
        A<X> ax;
      void f_nothrow() noexcept;
      B<f_nothrow> bn;   // OK: type of X deduced as bool

    end example]

  9. Change [temp.deduct.type] paragraph 19 as follows:

  10. If P has a form that contains <i>, and if the type of i differs from the type of the corresponding template parameter of the template named by the enclosing simple-template-id, deduction fails. If P has a form that contains [i], and if the type of i is not an integral type, deduction fails.131 If P has a form that includes noexcept(i) and the type of i is not bool, deduction fails.
    [Example 12: ...
  11. Add the following as a new section preceding C.1.6 [diff.cpp20.library]:

  12. C.1.4 Clause 13: templates [diff.cpp20.temp]

    Affected subclause: [temp.deduct.type]
    Change: Deducing template arguments from exception specifications.
    Rationale: Facilitate generic handling of throwing and non-throwing functions.
    Effect on original feature: Valid ISO C++20 code may be ill-formed in this revision of C++.

    [Example 1:

       template<bool> struct A { };
       template<bool B> void f(void (*)(A<B>) noexcept(B));
       void g(A<false>) noexcept;
       void h() {
         f(g);    // ill-formed; previously well-formed.

    end example]

Date: 2018-04-15.00:00:00

Notes from the April, 2018 teleconference:

Although this appears to be an obvious omission, CWG felt that EWG should weigh in on whether this capability should be supported or not.

EWG guidance (January, 2021):

Modify the Standard such that the value of a constant in a noexcept-specifier can be deduced. See vote.

Date: 2022-07-15.00:00:00

[Accepted at the July, 2022 meeting.]

The list of deducible forms in [temp.deduct.type] paragraph 8 does not include the ability to deduce the value of the constant in a noexcept-specifier, although implementations appear to allow it.

Date User Action Args
2022-08-19 07:54:33adminsetstatus: ready -> cd6
2022-06-03 20:33:19adminsetmessages: + msg6841
2022-06-03 20:33:19adminsetstatus: open -> ready
2022-04-21 13:08:11adminsetstatus: extension -> open
2018-04-11 00:00:00adminsetmessages: + msg6218
2018-04-11 00:00:00adminsetstatus: open -> extension
2017-09-06 00:00:00admincreate