www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Typesafe variadic functions requiring at least one argument

reply pineapple <meapineapple gmail.com> writes:
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
next sibling parent reply kinke <noone nowhere.com> writes:
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
parent kinke <noone nowhere.com> writes:
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
prev sibling next sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
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
parent pineapple <meapineapple gmail.com> writes:
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
prev sibling parent Michael Coulombe <kirsybuu gmail.com> writes:
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