You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The normal form of a concept-id C<A1, A2, ..., An> is the normal form of the constraint-expression of C, after substituting A1, A2, ..., An for C's respective template parameters in the parameter mappings in each atomic constraint. If any such substitution results in an invalid type or expression, the program is ill-formed; no diagnostic is required.
Consider this example:
template<typename T> concept A = T::value || true;
template<typename U> concept C = A<U*>;
template<classT>
requires C<T> voidfun(T){}
intmain(){
int a = 0;
fun<int&>(a);
}
In this case, the template parameter that appears in the atomic constraint is T, where the mapping is T↦ U*, and the template argument in concept-id C<int&> is int&, when undergoing the normalization of C<int&>, C's template parameter U that appears in the parameter mapping is substituted by int&, such substitution results in an invalid type int&*. By this logic, the program should be ill-formed. For this example, Clang rejects it but GCC accepts it and calls the specialization. Clang gave a kindly reminder:
<source>:2:37: note: because substituted constraint expression is ill-formed:
'type name' declared as a pointer to a reference of type 'int &'
Another case based on the above concept-id for which they have a divergence is
bool r = !C<int&>;
std::cout<< r;
GCC prints 0 while Clang prints 1.
The divergence might raise from the confusion mentioned in #5389.
In summary of these two issues, [temp.constr.normal] p1.4 might be changed to
The normal form of a concept-id C<A1, A2, ..., An> is the normal form of the constraint-expression of C, after substituting A1, A2, ..., An for C's respective template parameters that appear in concept-ids(if any) in C's constraint-expression and mapping C's respective template parameters that appear in C's constraint-expression to A1, A2, ..., An. If any such substitution results in an invalid type or expression, the program is ill-formed; no diagnostic is required.
This modification conforms to the definition of parameter mapping
An atomic constraint is formed from an expression E and a mapping from the template parameters that appear within E to template arguments that are formed via substitution during constraint normalization in the declaration of a constrained entity (and, therefore, can involve the unsubstituted template parameters of the constrained entity), called the parameter mapping ([temp.constr.decl]).
The text was updated successfully, but these errors were encountered:
The implementation divergence seems from CWG2369 which is only implemented by GCC currently. (The status quo hasn't changed for several years, though.)
Uh oh!
There was an error while loading. Please reload this page.
[temp.constr.normal] p1.4 says
Consider this example:
In this case, the template parameter that appears in the atomic constraint is
T
, where the mapping isT↦ U*
, and the template argument in concept-idC<int&>
isint&
, when undergoing the normalization ofC<int&>
,C
's template parameterU
that appears in the parameter mapping is substituted byint&
, such substitution results in an invalid typeint&*
. By this logic, the program should be ill-formed. For this example, Clang rejects it but GCC accepts it and calls the specialization. Clang gave a kindly reminder:@jensmaurer
Another case based on the above
concept-id
for which they have a divergence isGCC prints
0
while Clang prints1
.The divergence might raise from the confusion mentioned in #5389.
In summary of these two issues, [temp.constr.normal] p1.4 might be changed to
This modification conforms to the definition of parameter mapping
The text was updated successfully, but these errors were encountered: