## digitalmars.D.learn - How do I simulate variadic parameters for template (range) functions?

• Andrej Mitrovic (47/47) Aug 24 2011 Here's what I can do with a variadic function:
• Timon Gehr (4/51) Aug 24 2011 Workaround: You can make it a templated function with no template
• Steven Schveighoffer (14/61) Aug 24 2011 maybe:
• Timon Gehr (8/80) Aug 24 2011 This should do (although it would probably be even better to have a
• Jonathan M Davis (4/92) Aug 24 2011 std.typetuple has anySatisfy and allSatisfy (though that's a rather biza...
• Jacob Carlborg (5/52) Aug 24 2011 Use a variadic template function and check if the first argument is a
Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
```Here's what I can do with a variadic function:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a[a.countUntil(7) .. \$]);
process(1);
}

void process(int[] vals...)
{
foreach (val; vals)
{
}
}

Very simple, pass one or multiple arguments. But then I thought about
using the `until` template instead of countUntil. However `until`
returns a range. So my next guess was to write:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a.until(7));  // ok
process(4);  // error since 4 is not a range
}

void process(Range)(Range vals) if (isInputRange!Range &&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

Is it somehow possible to automatically convert a literal to a range?
making an overload that only takes an int and constructing a simple
input range around it so it can be passed to process(), e.g.:

void process(Range)(Range vals) if (isInputRange!Range &&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

void process(int arg)
{
process(makeInputRange(arg));  // make an input range, pass to
above process()
}

But I can't overload templated and non-templated functions, I think
this is one of those old-standing bugs.
```
Aug 24 2011
Timon Gehr <timon.gehr gmx.ch> writes:
```On 08/24/2011 07:40 PM, Andrej Mitrovic wrote:
Here's what I can do with a variadic function:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a[a.countUntil(7) .. \$]);
process(1);
}

void process(int[] vals...)
{
foreach (val; vals)
{
}
}

Very simple, pass one or multiple arguments. But then I thought about
using the `until` template instead of countUntil. However `until`
returns a range. So my next guess was to write:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a.until(7));  // ok
process(4);  // error since 4 is not a range
}

void process(Range)(Range vals) if (isInputRange!Range&&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

Is it somehow possible to automatically convert a literal to a range?
making an overload that only takes an int and constructing a simple
input range around it so it can be passed to process(), e.g.:

void process(Range)(Range vals) if (isInputRange!Range&&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

void process(int arg)
{
process(makeInputRange(arg));  // make an input range, pass to
above process()
}

But I can't overload templated and non-templated functions, I think
this is one of those old-standing bugs.

Workaround: You can make it a templated function with no template
arguments and wrap a non-templated version, if it is important that the
implementation is not a template.
```
Aug 24 2011
"Steven Schveighoffer" <schveiguy yahoo.com> writes:
```On Wed, 24 Aug 2011 13:40:38 -0400, Andrej Mitrovic
<andrej.mitrovich gmail.com> wrote:

Here's what I can do with a variadic function:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a[a.countUntil(7) .. \$]);
process(1);
}

void process(int[] vals...)
{
foreach (val; vals)
{
}
}

Very simple, pass one or multiple arguments. But then I thought about
using the `until` template instead of countUntil. However `until`
returns a range. So my next guess was to write:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a.until(7));  // ok
process(4);  // error since 4 is not a range
}

void process(Range)(Range vals) if (isInputRange!Range &&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

Is it somehow possible to automatically convert a literal to a range?
making an overload that only takes an int and constructing a simple
input range around it so it can be passed to process(), e.g.:

void process(Range)(Range vals) if (isInputRange!Range &&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

void process(int arg)
{
process(makeInputRange(arg));  // make an input range, pass to
above process()
}

But I can't overload templated and non-templated functions, I think
this is one of those old-standing bugs.

maybe:

void process(Range)(Range vals) if (isInputRange!Range &&
is(ElementType!Range == int))
{
...
}

void process(Vals...)(Vals vals) if (allValsElementsAreInt)
{
...
}

Note that I'm not sure what to put for allValsElementsAreInt...

-Steve
```
Aug 24 2011
Timon Gehr <timon.gehr gmx.ch> writes:
```On 08/24/2011 07:54 PM, Steven Schveighoffer wrote:
On Wed, 24 Aug 2011 13:40:38 -0400, Andrej Mitrovic
<andrej.mitrovich gmail.com> wrote:

Here's what I can do with a variadic function:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a[a.countUntil(7) .. \$]);
process(1);
}

void process(int[] vals...)
{
foreach (val; vals)
{
}
}

Very simple, pass one or multiple arguments. But then I thought about
using the `until` template instead of countUntil. However `until`
returns a range. So my next guess was to write:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a.until(7)); // ok
process(4); // error since 4 is not a range
}

void process(Range)(Range vals) if (isInputRange!Range &&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

Is it somehow possible to automatically convert a literal to a range?
making an overload that only takes an int and constructing a simple
input range around it so it can be passed to process(), e.g.:

void process(Range)(Range vals) if (isInputRange!Range &&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

void process(int arg)
{
process(makeInputRange(arg)); // make an input range, pass to
above process()
}

But I can't overload templated and non-templated functions, I think
this is one of those old-standing bugs.

maybe:

void process(Range)(Range vals) if (isInputRange!Range &&
is(ElementType!Range == int))
{
...
}

void process(Vals...)(Vals vals) if (allValsElementsAreInt)
{
...
}

Note that I'm not sure what to put for allValsElementsAreInt...

-Steve

This should do (although it would probably be even better to have a
forAll template and a predicate template).

template allElementsAreInt(T...){
static if(T.length==0) enum allElementsAreInt=true;
else enum allElementsAreInt=is(typeof(T[0])==int)
&& allElementsAreInt!(T[1..\$]);
}
```
Aug 24 2011
"Jonathan M Davis" <jmdavisProg gmx.com> writes:
```On Wednesday, August 24, 2011 11:00 Timon Gehr wrote:
On 08/24/2011 07:54 PM, Steven Schveighoffer wrote:
On Wed, 24 Aug 2011 13:40:38 -0400, Andrej Mitrovic

<andrej.mitrovich gmail.com> wrote:
Here's what I can do with a variadic function:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a[a.countUntil(7) .. \$]);
process(1);
}

void process(int[] vals...)
{
foreach (val; vals)
{
}
}

Very simple, pass one or multiple arguments. But then I thought about
using the `until` template instead of countUntil. However `until`
returns a range. So my next guess was to write:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a.until(7)); // ok
process(4); // error since 4 is not a range
}

void process(Range)(Range vals) if (isInputRange!Range &&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

Is it somehow possible to automatically convert a literal to a range?
making an overload that only takes an int and constructing a simple
input range around it so it can be passed to process(), e.g.:

void process(Range)(Range vals) if (isInputRange!Range &&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

void process(int arg)
{
process(makeInputRange(arg)); // make an input range, pass to
above process()
}

But I can't overload templated and non-templated functions, I think
this is one of those old-standing bugs.

maybe:

void process(Range)(Range vals) if (isInputRange!Range &&
is(ElementType!Range == int))
{
...
}

void process(Vals...)(Vals vals) if (allValsElementsAreInt)
{
...
}

Note that I'm not sure what to put for allValsElementsAreInt...

-Steve

This should do (although it would probably be even better to have a
forAll template and a predicate template).

template allElementsAreInt(T...){
static if(T.length==0) enum allElementsAreInt=true;
else enum allElementsAreInt=is(typeof(T[0])==int)
&& allElementsAreInt!(T[1..\$]);
}

std.typetuple has anySatisfy and allSatisfy (though that's a rather bizarre
place to put them IMHO).

- Jonathan M Davis
```
Aug 24 2011
Jacob Carlborg <doob me.com> writes:
```On 2011-08-24 19:40, Andrej Mitrovic wrote:
Here's what I can do with a variadic function:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a[a.countUntil(7) .. \$]);
process(1);
}

void process(int[] vals...)
{
foreach (val; vals)
{
}
}

Very simple, pass one or multiple arguments. But then I thought about
using the `until` template instead of countUntil. However `until`
returns a range. So my next guess was to write:

void main()
{
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];

process(a.until(7));  // ok
process(4);  // error since 4 is not a range
}

void process(Range)(Range vals) if (isInputRange!Range&&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

Is it somehow possible to automatically convert a literal to a range?
making an overload that only takes an int and constructing a simple
input range around it so it can be passed to process(), e.g.:

void process(Range)(Range vals) if (isInputRange!Range&&
is(ElementType!Range == int))
{
foreach (val; vals)
{
}
}

void process(int arg)
{
process(makeInputRange(arg));  // make an input range, pass to
above process()
}

But I can't overload templated and non-templated functions, I think
this is one of those old-standing bugs.

Use a variadic template function and check if the first argument is a
range or not.

--
/Jacob Carlborg
```
Aug 24 2011