digitalmars.D.learn - Typesafe variadic functions requiring at least one argument
- pineapple (8/8) Jul 06 2016 I'd like to do something like this but it doesn't seem to be
- kinke (7/15) Jul 06 2016 I don't really know what you're looking for. But you need to drop
- kinke (9/9) Jul 06 2016 In case you want a compile error if no arguments are specified,
- Jonathan M Davis via Digitalmars-d-learn (50/58) Jul 06 2016 That's not legal, because template constraints only go on templates, and
- pineapple (2/12) Jul 07 2016 Exactly what I was looking for. Thanks!
- Michael Coulombe (11/19) Jul 07 2016 Is this close enough?
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?
Jul 06 2016
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); ... }
Jul 06 2016
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(); }
Jul 06 2016
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
Jul 06 2016
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!
Jul 07 2016
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); }
Jul 07 2016