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
Consider:
template <typename T> concept C = requires (typename T::type x) { x + 1; }; static_assert(!C<int>);
All implementations accept this translation unit. However, the rule in 7.5.8.1 [expr.prim.req.general] paragraph 5 does not cover the parameter-declaration-clause::
The substitution of template arguments into a requires-expression may result in the formation of invalid types or expressions in its requirements or the violation of the semantic constraints of those requirements. In such cases, the requires-expression evaluates tofalse
; it does not cause the program to be ill-formed. The substitution and semantic constraint checking proceeds in lexical order and stops when a condition that determines the result of the requires-expression is encountered. If substitution (if any) and semantic constraint checking succeed, the requires-expression evaluates totrue
.
Proposed resolution (approved by CWG 2023-06-17):
Change in 7.5.8.1 [expr.prim.req.general] paragraph 5:
The substitution of template arguments into a requires-expression may result in the formation of invalid types or expressions in its parameter-declaration-clause (if any) or its requirements or the violation of the semantic constraints of those requirements. In such cases, ...
CWG 2023-11-09
The initial example is not the point of the issue, but the very similar following case:
template <typename T>
constexpr bool b = requires (T::type x) { x + 1; };
static_assert(!b<int>); // de-jure ill-formed, but widely accepted by implementations
Users were vocal they wanted this not to be an error, but just a substitution failure. Reportedly, the original design intent was that this situation is a hard error, though.
Soliciting guidance from EWG how to handle this issue via paper issue 1695.
EWG 2024-03-18
EWG invites a paper to propose a change.