How do I simulate variadic parameters for template (range) functions?

Timon Gehr timon.gehr at gmx.ch
Wed Aug 24 11:00:08 PDT 2011


On 08/24/2011 07:54 PM, Steven Schveighoffer wrote:
> On Wed, 24 Aug 2011 13:40:38 -0400, Andrej Mitrovic
> <andrej.mitrovich at 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?
>> I really miss the convenience of variadic functions. I thought about
>> 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..$]);
}




More information about the Digitalmars-d-learn mailing list