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

2024-04-18


2602. consteval defaulted functions

Section: 9.2.6  [dcl.constexpr]     Status: C++23     Submitter: Aaron Ballman     Date: 2022-06-16

[Accepted as a DR at the February, 2023 meeting.]

It is not clear whether a defaulted consteval function is still an immediate function even if it is not a valid constexpr function. For example:

  template <typename Ty>
  struct A {
    Ty n;
    consteval A() {}
  };

  template <typename Ty>
  struct B {
    Ty n;
    consteval B() = default;
  };

  A<int> a;
  B<int> b;

The declarations of a and b should both fail due to an uninitialized member n in each of A and B. The = default; should not make a difference. However, there is implementation divergence. We should be able to lean on 7.7 [expr.const] bullet 5.5 to handle this when the immediate invocation is required.

Possible resolution:

Change in 9.2.6 [dcl.constexpr] paragraph 7 as follows:

If the instantiated template specialization of a constexpr templated function template or member function of a class template would fail to satisfy the requirements for a constexpr function, that specialization is still a constexpr function, even though a call to such a function cannot appear in a constant expression. Similarly, if the instantiated template specialization of a consteval templated function would fail to satisfy the requirements for a consteval function, that specialization is still an immediate function, even though an immediate invocation would be ill-formed. If no specialization of the template would satisfy the requirements for a constexpr or consteval function when considered as a non-template function, the template is ill-formed, no diagnostic required.

Proposed resolution (August, 2022) [SUPERSEDED]:

Change in 9.2.6 [dcl.constexpr] paragraph 4 as follows:

If the instantiated template specialization of a constexpr templated function template or member function of a class template would fail to satisfy the requirements for a constexpr function, that specialization is still a constexpr function, even though a call to such a function cannot appear in a constant expression. Similarly, if the instantiated template specialization of a consteval templated function would fail to satisfy the requirements for a consteval function, that specialization is still an immediate function, even though an immediate invocation would be ill-formed.

Additional notes (November, 2022)

The proposed wording is possibly not addressing the point of the issue; the issue has been retracted from the WG21 plenary straw polls for further consideration in CWG.

Proposed resolution (approved by CWG 2023-01-27):

  1. Change in 9.2.6 [dcl.constexpr] paragraph 3 as follows:

    The definition of a constexpr function shall satisfy the following requirements: A function is constexpr-suitable if:
    • it shall is not be a coroutine (9.5.4 [dcl.fct.def.coroutine]); , and
    • if the function is a constructor or destructor, its class shall does not have any virtual base classes.
    Except for instantiated constexpr functions, non-templated constexpr functions shall be constexpr-suitable.
  2. Delete 9.2.6 [dcl.constexpr] paragraph 4:

    If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function, that specialization is still a constexpr function, even though a call to such a function cannot appear in a constant expression.
  3. Change in 7.5.5.2 [expr.prim.lambda.closure] paragraph 5 as follows:

    ... The function call operator or any given operator template specialization is a constexpr function if either the corresponding lambda-expression's parameter-declaration-clause is followed by constexpr or consteval, or it satisfies the requirements for a constexpr function is constexpr-suitable (9.2.6 [dcl.constexpr]). ...
  4. Change in 7.7 [expr.const] bullet 5.5 as follows:

    • an invocation of an instantiated constexpr function that fails to satisfy the requirements for a constexpr function is not constexpr-suitable;
  5. Change in 9.5.2 [dcl.fct.def.default] paragraph 3 as follows:

    A function explicitly defaulted on its first declaration is implicitly inline (9.2.8 [dcl.inline]), and is implicitly constexpr (9.2.6 [dcl.constexpr]) if it satisfies the requirements for a constexpr function is constexpr-suitable.
  6. Change in 11.4.7 [class.dtor] paragraph 9 as follows:

    A defaulted destructor is a constexpr destructor if it satisfies the requirements for a constexpr function is constexpr-suitable (9.2.6 [dcl.constexpr]).