> Ts=<int,int>, Us=<> , but as far as I could tell, Anoop rejects that outcome.Note that I don't actually reject `Ts={int, int}`, `Us={ }`. What I am objecting is that the program 1.1 is ill-formed with `U` not being { } as per the current wording instead of being1) well-formed with `Ts={int, int}`, `Us={ }` assuming packs are greedy(no ambiguity) or2) ill-formed with `Ts={int, int}`, `Us={ }` assuming this is ambiguous instead of being greedy or3) ill-formed with `Ts={int, int}`, `Us={}` assuming packs are greedy(no ambiguity). If this point 3 is what the standard currently supports then it doesn't make sense because a parameter pack is allowed to be empty so that Ts={int, int}, Us={ } is an expected output and the program should be well-formed instead of ill-formed. Note again that Ts={int, int}, Us={ } is an expected output in this point 3 because there is no ambiguity interpretation used here in this point. These interpretations are separate from each other as also noted below.
|----------------------------------------------------------|-----------------|-----|-------|------|------|----------|
| Template | Usage | GCC | Clang | MSVC | EDG | Standard |
|----------------------------------------------------------|-----------------|-----|-------|------|------|----------|
| template<class... Ts, class... Us> int f1(); | | ✓ | ✓ | Err | Warn | Err |
| template<class... Ts, class... Us> int f1(); | f1<int, int> | ✓ | ✓ | Err | Warn | Err |
| template<class... Ts, int... Us> int f2(); | | ✓ | ✓ | Err | Warn | Err |
| template<class... Ts, int... Us> int f2(); | f2<int, 1> | Err | Err | Err | Err | Err |
| template<class... Ts, int U> int f3(); | | ✓ | ✓ | Err | Warn | Err |
| template<class... Ts, int U> int f3(); | f3<int, 1> | Err | Err | Err | Err | Err |
| template<class... Ts, template<class> class U> int f4(); | | ✓ | ✓ | Err | Warn | Err |
| template<class... Ts, template<class> class U> int f4(); | f4<int, C> | Err | Err | Err | Err | Err |
| template<class... Ts, int U, class... Vs> int f5(); | | ✓ | ✓ | Err | Warn | Err |
| template<class... Ts, int U, class... Vs> int f5(); | f5<int, 1> | Err | Err | Err | Err | Err |
| template<class... Ts, int U, class... Vs> int f5(); | f5<1, int> | Err | Err | Err | Err | Err |
| template<class... Ts, int U, class... Vs> int f5(); | f5<int, 1, int> | Err | Err | Err | Err | Err |
| template<class... Ts, int... Us, class... Vs> int f6(); | | ✓ | ✓ | Err | Warn | Err |
| template<class... Ts, int... Us, class... Vs> int f6(); | f6<int> | ✓ | ✓ | Err | Warn | Err |
| template<class... Ts, int... Us, class... Vs> int f6(); | f6<int, int> | ✓ | ✓ | Err | Warn | Err |
| template<class... Ts, int... Us, class... Vs> int f6(); | f6<int, 1> | Err | Err | Err | Err | Err |
| template<class... Ts, int... Us, class... Vs> int f6(); | f6<int, 1, int> | Err | Err | Err | Err | Err |
| template<auto... Ts, int... Us> int f7(); | | ✓ | ✓ | Err | Warn | Err |
| template<auto... Ts, int... Us> int f7(); | f7<1> | ✓ | ✓ | Err | Warn | Err |
| template<auto... Ts, int... Us> int f7(); | f7<&i, 1> | ✓ | ✓ | Err | Warn | Err |
| template<int... Ts, auto... Us> int f8(); | | ✓ | ✓ | Err | Warn | Err |
| template<int... Ts, auto... Us> int f8(); | f7<1> | ✓ | ✓ | Err | Warn | Err |
| template<int... Ts, auto... Us> int f8(); | f7<&i> | Err | Err | Err | Err | Err |
| template<same_as<char> auto... Ts, same_as<int> auto... Us> int f9(); | | ✓ | ✓ | Err | Unsupp | Err |
| template<same_as<char> auto... Ts, same_as<int> auto... Us> int f9(); | f9<1> | Err | Err | Err | Unsupp | Err |
| template<same_as<char> auto... Ts, same_as<int> auto... Us> int f9(); | f9<'x', 1> | Err | Err | Err | Unsupp | Err |
NOTE:Just to sum up some things, according to the paper `template<typename... T, typename... U> f(){}` is ill-formed because `U` and `T` have the same underlying types(meaning they both are "type" parameter packs)