Re: Typesafe variadic functions requiring at least one argument

2016-07-07 Thread pineapple via Digitalmars-d-learn

On Thursday, 7 July 2016 at 03:52:40 UTC, Jonathan M Davis wrote:
However, it looks like you can combine those two types of 
variadic functions to get more or less what you want (albeit 
more verbosely).  e.g.


template isInt(T) { enum isInt = is(std.traits.Unqual!T == 
int); }


void test(Args...)(Args args)
if(args.length > 0 && std.meta.allSatisfy!(isInt, Args))
{
test2(args);
}


Exactly what I was looking for. Thanks!


Re: Typesafe variadic functions requiring at least one argument

2016-07-07 Thread Michael Coulombe via Digitalmars-d-learn

On Wednesday, 6 July 2016 at 19:50:11 UTC, pineapple wrote:
I'd like to do something like this but it doesn't seem to be 
legal -


void test(int[] ints...) if(ints.length){
// stuff
}

Not being able to specify this interferes with how I'd like to 
define my method overloads. What's the best way to achieve what 
I'm looking for?


Is this close enough?

void test(int first, int[] rest...) {
auto ints = only(first).chain(rest);
// stuff
}
void main() {
//test(); // fails to compile
test(1);
test(1,2,3);
}


Re: Typesafe variadic functions requiring at least one argument

2016-07-06 Thread Jonathan M Davis via Digitalmars-d-learn
On Wednesday, July 06, 2016 19:50:11 pineapple via Digitalmars-d-learn wrote:
> I'd like to do something like this but it doesn't seem to be
> legal -
>
>  void test(int[] ints...) if(ints.length){
>  // stuff
>  }
>
> Not being able to specify this interferes with how I'd like to
> define my method overloads. What's the best way to achieve what
> I'm looking for?

That's not legal, because template constraints only go on templates, and
that function isn't templated. It's using what the spec calls a typesafe
variadic function. If you want to restrict the length at compile time, you'd
need to use a variadic template function (which is what most D code seems to
use when a variadic function is required). e.g.

void test(Args...)(Args args)
if(args.length > 0)
{
// stuff
}

But that function will take arguments of any type and does not give you an
array. If you wanted to restrict it to ints, you'd have to do something like

template isInt(T) { enum isInt = is(std.traits.Unqual!T == int); }

void test(Args...)(Args args)
if(args.length > 0 && std.meta.allSatisfy!(isInt, Args))
{
// stuff
}

If you want to just use a "typesafe" variadic function as in your example,
you're going to need to do a runtime check. e.g.

void test(int[] ints...)
{
assert(!ints.empty);
// stuff
}

However, it looks like you can combine those two types of variadic functions
to get more or less what you want (albeit more verbosely).  e.g.

template isInt(T) { enum isInt = is(std.traits.Unqual!T == int); }

void test(Args...)(Args args)
if(args.length > 0 && std.meta.allSatisfy!(isInt, Args))
{
test2(args);
}

void test2(int[] ints...)
{
// stuff
}

or

template isInt(T) { enum isInt = is(std.traits.Unqual!T == int); }

void test(Args...)(Args args)
if(args.length > 0 && std.meta.allSatisfy!(isInt, Args))
{
static void test2(int[] ints...)
{
// stuff
}
test2(args);
}

- Jonathan M Davis



Re: Typesafe variadic functions requiring at least one argument

2016-07-06 Thread kinke via Digitalmars-d-learn
In case you want a compile error if no arguments are specified, 
you can use something like this:


void foo()() { static assert(0); }
void foo(int[] ints...) { assert(ints); }

void main()
{
foo(1, 2, 3);
foo();
}


Re: Typesafe variadic functions requiring at least one argument

2016-07-06 Thread kinke via Digitalmars-d-learn

On Wednesday, 6 July 2016 at 19:50:11 UTC, pineapple wrote:
I'd like to do something like this but it doesn't seem to be 
legal -


void test(int[] ints...) if(ints.length){
// stuff
}

Not being able to specify this interferes with how I'd like to 
define my method overloads. What's the best way to achieve what 
I'm looking for?


I don't really know what you're looking for. But you need to drop 
the if condition - you can only specify them for templates as 
instantiation constraints. You may want to use a runtime check 
instead (the slice's size isn't available at compile-time - 
although it's known at the call site):


void test(int[] ints...] { assert(ints); ... }