This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
[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 functiontemplate or member function of a class templatewould 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 functiontemplate or member function of a class templatewould 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):
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:Except for instantiated constexpr functions, non-templated constexpr functions shall be constexpr-suitable.
- it
shallis notbea coroutine (9.5.4 [dcl.fct.def.coroutine]);, and- if the function is a constructor or destructor, its class
shalldoes not have any virtual base classes.
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.
Change in 7.5.6.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 itsatisfies the requirements for a constexpr functionis constexpr-suitable (9.2.6 [dcl.constexpr]). ...
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 functionis not constexpr-suitable;
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 itsatisfies the requirements for a constexpr functionis constexpr-suitable.
Change in 11.4.7 [class.dtor] paragraph 9 as follows:
A defaulted destructor is a constexpr destructor if itsatisfies the requirements for a constexpr functionis constexpr-suitable (9.2.6 [dcl.constexpr]).