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] p4 Partial ordering for a non-deduced context parameter #4879

Open
xmh0511 opened this issue Sep 8, 2021 · 3 comments

Comments

@xmh0511
Copy link
Contributor

xmh0511 commented Sep 8, 2021

In c++17, [temp.deduct.partial] p4 says

Each type nominated above from the parameter template and the corresponding type from the argument template are used as the types of P and A. If a particular P contains no template-parameters that participate in template argument deduction, that P is not used to determine the ordering.

After CWG2235, the emphasized wording was removed. Consider this example

template<class U>
struct unknow_content{
    using type = U;
};

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

template<class T, class U>
void fun(T, U){
    std::cout<<"2\n";
}
int main(){
   fun(0,0);
}

According to [temp.deduct.partial#3.1], the P/A pairs are formed from function parameter types without other requirements. Hence, in this partial ordering, the set of P/A pairs that determine the ordering consists of

P = typename unknow_content<T>::type / A = T' ,     P = T / A = U' 

P = T' / A = typename unknow_content<T>::type ,     P = U' / A = T

Which is more specialized than the other is essentially determined by that

If deduction succeeds for a given type, the type from the argument template is considered to be at least as specialized as the type from the parameter template.

Function template F is at least as specialized as function template G if, for each pair of types used to determine the ordering, the type from F is at least as specialized as the type from G. F is more specialized than G if F is at least as specialized as G and G is not at least as specialized as F.

Without the impact of the removed rule

If a particular P contains no template-parameters that participate in template argument deduction, that P is not used to determine the ordering.

[temp.deduct.type] p4

In certain contexts, however, the value does not participate in type deduction, but instead uses the values of template arguments that were either deduced elsewhere or explicitly specified.

does not apply here since P = typename unknow_content<T>::type does participate in deduction.

We can arguably says, the deduction fails for this pair P = typename unknow_content<T>::type / A = T' since that

If type deduction cannot be done for any P/A pair, ..., template argument deduction fails

Hence, in this example, #1 should have been more specialized than #2 after CWG2235, however, all implementations say they're ambiguous. See https://godbolt.org/z/9P1Tjr3WK

@xmh0511
Copy link
Contributor Author

xmh0511 commented Sep 8, 2021

Maybe, we could change the removed wording to be that

If a particular P is non-deduced, that P is not used to determine the ordering.

https://godbolt.org/z/YWEMd9adj

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

template<class T, class U>
void fun(T*, U){
    std::cout<<"2\n";
}
int main(){
   fun(0,0);
}

#1 is better. The proposal wording can also be suitable for the case concerned by CWG2235

template <class T> T f(int);        // #1
  template <class T, class U> T f(U); // #2
  void g() {
    f<int>(1);                        // calls #1
  }

@xmh0511
Copy link
Contributor Author

xmh0511 commented Sep 8, 2021

Incidentally, CWG2235 said #4 is better in the following example

template <class... T> struct V {}; 
  template <class... Ts, class... Us> void Foo(V<Ts...>, V<Us&...>) {} // #3 
  template <class... Us> void Foo(V<>, V<Us&...>) {}                   // #4 
  void h() { 
    Foo(V<>(), V<>()); 
  } 

However, in the current draft, it should be ambiguous. GCC and Clang have disagreements on this example. GCC reports ambiguous error while Clang accept it and selects #4. More details are located in https://stackoverflow.com/questions/66928493/several-examples-about-template-partial-ordering-to-which-gcc-and-clang-disagree

@xmh0511
Copy link
Contributor Author

xmh0511 commented Sep 9, 2021

@jensmaurer @jwakely Please have a look at this.

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