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.deduct.partial] The unclear points in partial ordering for function/class templates #5454

Open
xmh0511 opened this issue May 6, 2022 · 1 comment

Comments

@xmh0511
Copy link
Contributor

xmh0511 commented May 6, 2022

[temp.deduct.partial] p8 says

Using the resulting types P and A, the deduction is then done as described in [temp.deduct.type].

[temp.deduct.type] p1 says

an attempt is made to find template argument values (a type for a type parameter, a value for a non-type parameter, or a template for a template parameter) that will make P, after substitution of the deduced values (call it the deduced A), compatible with A.

[temp.func.order] p3 says

To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.

Consider this example:

template<class T, class U>
struct A{};

template<class T>
void fun(A<T,T>){
    std::cout<<"#1\n";
}

template<class T>
void fun(A<T, std::remove_reference_t<decltype(std::declval<T>())>>){
     std::cout<<"#2\n";
}

Take #1 as the argument template and #2 as the parameter template. Assume the unique type for T in #1 is TUnique1, hence A is A<TUnique1, TUnique1>, which compares with P that is A<T, std::remove_reference_t<decltype(std::declval<T>())>>, the first T in P is deduced to TUnique1, according to [temp.deduct.type] p4, the second T in P uses the value deduced for the first T. Back to [temp.deduct.type] p1, the result of the substitution is A<TUnique1, TUnique1> because std::remove_reference_t<decltype(std::declval<T>())> is T for any type T. The deduction of P from A success. Again,take #1 as the parameter template and #2 as the argument template, with the similar reason, the deduction of P from A success. We expect the call would be ambiguous, however, most implementations chose #1.

Consider a contrast example:

template<class T>
struct Wrapper{
    using type = T;
};

template<class T, class U>
struct A{};

template<class T>
void fun(A<T, typename Wrapper<T>::type>){
    std::cout<<"#1\n";
}

template<class T>
void fun(A<T, std::remove_reference_t<decltype(std::declval<T>())>>){
     std::cout<<"#2\n";
}

For any type T, the result of the substitution of typename Wrapper<T>::type is T. The call is ambiguous for a similar reason as above, at this time, implementations agree the call is ambiguous. More vague in partial ordering can be found here
https://stackoverflow.com/questions/31394260/template-partial-ordering-why-does-partial-deduction-succeed-here
https://stackoverflow.com/questions/42416993/class-template-specialization-partial-ordering-and-function-synthesis

The subject of the second question can be simplified as

template<class T, class U>
struct A{};

// template<class T>
// struct A<T,T>{};

// template<class T>
// struct A<T, decltype(T{})>{};

template<class T>
void fun(A<T,T>){
    std::cout<<"#1\n";
}

template<class T>
void fun(A<T, decltype(T{})>){
    std::cout<<"#2\n";
}
int main(){
   // A<int,int> c;  
   fun(A<int,int>{});
}

The call prints #1 but A<int,int> is ambiguous. However, the partial ordering of the class partial specializations should be equivalent to partial ordering of the function templates.

@xmh0511 xmh0511 changed the title [temp.deduct.partial] The substitution in patial ordering for function templates [temp.deduct.partial] The substitution in partial ordering for function templates May 6, 2022
@xmh0511 xmh0511 changed the title [temp.deduct.partial] The substitution in partial ordering for function templates [temp.deduct.partial] The substitution in partial ordering for function/class templates May 6, 2022
@xmh0511 xmh0511 changed the title [temp.deduct.partial] The substitution in partial ordering for function/class templates [temp.deduct.partial] The unclear points in partial ordering for function/class templates May 6, 2022
@xmh0511
Copy link
Contributor Author

xmh0511 commented May 6, 2022

Another vague point is whether the instantiation is performed for determining the actual type of argument template and the deduced A. According to the behavior of implementations, the instantiation is not performed for the type of the argument template in both partial orderings of function template and class template. For the deduced A, the instantiation is performed for the function template but is not performed for the class template. Specifically, for the unique type Unique

The A will be A<Unique, decltype(Unique{})> rather than A<Unique, Unique>(after instantiation). Assume A<T,T> is A with a synthesized unique type Unique2 and A<T, decltype(T{})> is P, for partial ordering of function template, the instantiation may happen for it after deducing A<T, decltype(T{})> from A<Unique2, Unique2>, the deduced A is A<Unique2, Unique2> that is compatible with A. For partial ordering class template, the instantiation is not performed(i.e. remain its original form), the deduced A is ``A<Unique2, decltype(Unique2{})>, which is not compatible with A<Unique2, Unique2>`.

The above conclusion is inspired by the behavior of implementations and the answers of @zygoloid. This part is vague in the standard.

BUT the deduced A' is not always possible to instantiate the final type to determine whether A' is compatible with A. Such as A<T, decltype(fun(T))>, different types of the argument will produce the different return types(if fun is overload set). In this case, it is not possible to determine the return type of fun when giving a unique type that is not concrete. In summary, whether the deduction success and how compatible are just vague in the partial ordering of both function templates and class templates.

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