On Tue, 15 Nov 2022 at 15:43, Arthur O'Dwyer via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Mon, Nov 14, 2022 at 1:08 PM Anoop Rana <ranaanoop986@gmail.com> wrote:
>  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 being

1)  well-formed with `Ts={int, int}`, `Us={ }` assuming packs are greedy(no ambiguity) or
2) ill-formed with `Ts={int, int}`, `Us={ }` assuming this is ambiguous instead of being greedy or
3) 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.

I think your classification into 1,2,3 doesn't make sense; but I've also just realized that I was wrong about the current state of affairs.

    template<class... Ts, class... Us> void f();
    f<int,int>();

is actually accepted today by both GCC and Clang (deducing Ts={int,int}, Us={}).
MSVC rejects the template declaration of `f` itself (even before it's ever called) with a hard error. I think MSVC's behavior is what the Standard strictly requires.

Yes, this is https://eel.is/c++draft/temp.param#14

It would be worth exploring to what extent the proposal here is affected if some of the packs can be deduced from function template arguments (etc.).
 
But this is highly relevant to your paper, because "Let's change the rules that everyone currently follows" is a harder sell than "Let's change the rules that 2/3 of vendors don't follow anyway." And ideally you'd be saying "Let's change the rules to the thing that 2/3 of vendors already do" (i.e., "standardize existing practice").  I don't think that's actually what you're saying, but, maybe it should be?

As before, the paper lacks actual motivation for why a working programmer would want this change (or any change in this area). The proposal increases the number of paint splotches that are valid C++ programs, but what is the actual benefit to a human C++ programmer?

Instead of spreading out your "before/after comparison" section vertically over three pages, I suggest you make a little table something like this:

|----------------------------------------------------------|-----------------|-----|-------|------|------|----------|

| 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 |


and then add another column on the end, "Proposed," with what you propose for each case.

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)

FWIW, I'd say "the same kind" rather than "the same underlying type," as the latter has a technical meaning already.
I'd like to see an example where the parser's kind-disambiguation rules come into play, like
    constexpr double PI = 3.14;  // red herring
    template<char... Ts, class... Us> int f10();  // currently ill-formed, proposed OK
    f10<char{}>();  // proposed OK with Ts={0} Us={}
    f10<char()>();  // proposed OK with Ts={} Us={char()}
    f10<char(int(3.14))>();  // proposed OK with Ts={3} Us={}
    f10<char(int(PI))>();  // proposed OK with Ts={} Us={char(int)}

A procedural note: You've labeled your mailing-list drafts PxxxxR0 and PxxxxR1. You should instead label them DxxxxR0 (draft revision 0) and DxxxxR0 (draft revision 1), and so on. When (if) you submit the paper to an actual mailing, you'll number that submission as PxxxxR0, and then start working on new drafts as DxxxxR1 (draft revision whatever).

HTH,
Arthur
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals