Thread overview
Variadic Template Pattern
Jul 09, 2017
FoxyBrown
Jul 10, 2017
Jonathan M Davis
Jul 10, 2017
Joel Nilsson
July 09, 2017
Hi, I have a proposal, wondering about your opinions.

Suppose one has a template function foo that accepts a variable number of parameters:

auto foo(T...)();

Suppose we actually want to have some type of order and type info instead:

auto foo(int, string)();

but we need a "variable" number of them such as

auto foo(int, string, int, string)();

auto foo(int, string, int, string, int, string)();

ad nausea.

We could simplify it all by allowing for a sort of pattern on the ... for variadics:

auto food((int,string)...)();


and, this, of course, expands to what was described earlier.


Now, this can be accomplished already with the single template method and foreach/static if testing the type, but that seems like it's excessively verbose.



July 09, 2017
On Sunday, July 9, 2017 9:21:03 PM MDT FoxyBrown via Digitalmars-d wrote:
> Hi, I have a proposal, wondering about your opinions.
>
> Suppose one has a template function foo that accepts a variable number of parameters:
>
> auto foo(T...)();
>
> Suppose we actually want to have some type of order and type info instead:
>
> auto foo(int, string)();
>
> but we need a "variable" number of them such as
>
> auto foo(int, string, int, string)();
>
> auto foo(int, string, int, string, int, string)();
>
> ad nausea.
>
> We could simplify it all by allowing for a sort of pattern on the ... for variadics:
>
> auto food((int,string)...)();
>
>
> and, this, of course, expands to what was described earlier.
>
>
> Now, this can be accomplished already with the single template method and foreach/static if testing the type, but that seems like it's excessively verbose.

A helper template could be written to use in a template constraint which checked that that number of arguments was a power of however many arguments you gave it and that they matched those types in that order. You'd probably need another helper to create a struct or something that held the pattern, since putting one AliasSeq in front of another would just merge them (e.g. matchPattern!(int, string, Args) wouldn't work), but I'm sure that it could be done, leaving you with something like

auto foo(Args...)()
    if(matchPattern!(Pattern!(int, string), Args))
{
    ...
}

And yes, it's a bit more verbose than your suggestion, but it's a lot less verbose and more reusable than manually checking with foreach and static assertions - and it doesn't require a language change, just enough template-foo to write the helper template.

- Jonathan M Davis

July 10, 2017
On Sunday, 9 July 2017 at 21:21:03 UTC, FoxyBrown wrote:
> *snip*


If I understand what you want to achieve correctly, this can sort of be done with tuples:

void func(Tuple!(int, string)[] args...){
  args[0][0] // first int
  args[1][0] // second int
  args[0][1] // first string
  // and so on
}

Of course you would have to pass tuples as the arguments, so it's fairly verbose:

void func(tuple(1, "one"), tuple(2, "two"), tuple(3, "three"));