Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[temp.constr.normal] p1.4 The implementations have a divergence for substitution in the normalization of a concept-id #5461

Open
xmh0511 opened this issue May 10, 2022 · 0 comments

Comments

@xmh0511
Copy link
Contributor

xmh0511 commented May 10, 2022

[temp.constr.normal] p1.4 says

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<class T>
requires C<T> void fun(T){}

int main(){
    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 &'


@jensmaurer

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]).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant