Re: Typesafe variadic functions requiring at least one argument
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
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
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
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
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); ... }