www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Variadic templates

reply Walter Bright <newshound digitalmars.com> writes:
See http://www.digitalmars.com/d/variadic-function-templates.html

Why now? Because it's such a pain to do template programming without 
them, and because I wanted to have a good signals and slots 
implementation. That was the last piece needed to make S&S work right 
(unless I'm way off track with it).

There's a lot of unexplored territory with the tuples, they should be 
able to do a lot more than the current rather limited ability.
Nov 02 2006
next sibling parent reply Oskar Linde <olREM OVEnada.kth.se> writes:
Walter Bright wrote:

 See http://www.digitalmars.com/d/variadic-function-templates.html
 
 Why now? Because it's such a pain to do template programming without
 them, and because I wanted to have a good signals and slots
 implementation. That was the last piece needed to make S&S work right
 (unless I'm way off track with it).

This looks excellent. Supporting both a head-tail recursive variant and the indexable/foreachable tuple is brilliant. This will tremendously simplify much of my code and remove the hard limits on number of arguments. I also wish dmd gets better at inlining long chains of recursive template functions.
 There's a lot of unexplored territory with the tuples, they should be
 able to do a lot more than the current rather limited ability.

I am really excited about the possibilities here. Will tuples become real types or a meta-types? From the examples you show, I'd presume there is an implicit tuple expansion when calling void foo(int a, int b) {} as foo(t); where t is a tuple of (int,int) ? will it be possible to declare a function such as taking a specific tuple argument and use tuples as return values etc? As I said, I think this looks great. We are no longer in the vicinity of D 1.0... We are already at 2.0 :) /Oskar
Nov 02 2006
next sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Oskar Linde wrote:
 There's a lot of unexplored territory with the tuples, they should be
 able to do a lot more than the current rather limited ability.

types or a meta-types?

My current thought is that they will never be types, i.e. you will not be able to have a "pointer to tuple" or "array of tuples". Also, they will always be statically fixed at compile time. A tuple will simply be a shorthand notation for a sequence of types or expressions.
 From the examples you show, I'd presume there is an implicit tuple expansion
 when calling
 
 void foo(int a, int b) {}
 
 as foo(t); where t is a tuple of (int,int) ?

That's right. Those two declarations are the same thing. A function parameter list is a tuple.
 will it be possible to declare a function such as taking a specific tuple
 argument

I'm not sure what you mean. A function's parameter types *are* a tuple.
 and use tuples as return values etc?

That's something I want to make work.
Nov 02 2006
parent reply =?iso-8859-1?q?Knud_S=F8rensen?= <12tkvvb02 sneakemail.com> writes:
On Thu, 02 Nov 2006 02:02:35 -0800, Walter Bright wrote:

 Oskar Linde wrote:
 There's a lot of unexplored territory with the tuples, they should be
 able to do a lot more than the current rather limited ability.

types or a meta-types?

My current thought is that they will never be types, i.e. you will not be able to have a "pointer to tuple" or "array of tuples". Also, they will always be statically fixed at compile time. A tuple will simply be a shorthand notation for a sequence of types or expressions.
 From the examples you show, I'd presume there is an implicit tuple expansion
 when calling
 
 void foo(int a, int b) {}
 
 as foo(t); where t is a tuple of (int,int) ?

That's right. Those two declarations are the same thing. A function parameter list is a tuple.

tuple t=(7, 'a', 6.8); print t; // for print(7, 'a', 6.8)
 will it be possible to declare a function such as taking a specific tuple
 argument

I'm not sure what you mean. A function's parameter types *are* a tuple.
 and use tuples as return values etc?

That's something I want to make work.

Then you could write something like this. print func1 func2 t; // for print(func1(func2(7, 'a', 6.8)));
Nov 02 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Knud Sørensen wrote:
 Will something like this be possible ??
 
 tuple t=(7, 'a', 6.8);

Something like that.
  print t; // for print(7, 'a', 6.8)

It would be: print(t);
Nov 02 2006
parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Walter Bright wrote:
 Knud Sørensen wrote:
 Will something like this be possible ??

 tuple t=(7, 'a', 6.8);

Something like that.
  print t; // for print(7, 'a', 6.8)

It would be: print(t);

What about the comma operator? It would be perfect for creating tuples, and very consistent with the way functions are called. For example print(7,'a',6.8) passes to tuple (7,'a',6.8) to the function print. L.
Nov 04 2006
next sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Lionello Lunesu wrote:
 Walter Bright wrote:
 Knud Sørensen wrote:
 Will something like this be possible ??

 tuple t=(7, 'a', 6.8);

Something like that.
  print t; // for print(7, 'a', 6.8)

It would be: print(t);

What about the comma operator? It would be perfect for creating tuples, and very consistent with the way functions are called. For example print(7,'a',6.8) passes to tuple (7,'a',6.8) to the function print.

For creating tuples, the following works: template Tuple(T...) { alias T Tuple; } alias Tuple!(7, 'a', 6.8) t; print(t);
Nov 04 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Walter Bright" <newshound digitalmars.com> wrote in message 
news:eihm0v$1n22$2 digitaldaemon.com...

 For creating tuples, the following works:

 template Tuple(T...)
 {
     alias T Tuple;
 }

 alias Tuple!(7, 'a', 6.8) t;
 print(t);

But: alias Tuple!(4, 5, Tuple!("hi", "bye")) t2; <DMD Crash> I guess I should put this in Bugzilla if it's not there already..
Nov 04 2006
parent Walter Bright <newshound digitalmars.com> writes:
Jarrett Billingsley wrote:
 alias Tuple!(4, 5, Tuple!("hi", "bye")) t2;
 
 <DMD Crash>
 
 I guess I should put this in Bugzilla if it's not there already.. 

I'll fix it regardless <g>.
Nov 05 2006
prev sibling parent reply =?iso-8859-1?q?Knud_S=F8rensen?= <12tkvvb02 sneakemail.com> writes:
On Sat, 04 Nov 2006 10:20:37 +0200, Lionello Lunesu wrote:

 Walter Bright wrote:
 Knud Sørensen wrote:
 Will something like this be possible ??

 tuple t=(7, 'a', 6.8);

Something like that.
  print t; // for print(7, 'a', 6.8)

It would be: print(t);

What about the comma operator? It would be perfect for creating tuples, and very consistent with the way functions are called. For example print(7,'a',6.8) passes to tuple (7,'a',6.8) to the function print. L.

Did you mean like this. tuple t=7,'a',6.8; print(t);
Nov 04 2006
parent Lionello Lunesu <lio lunesu.remove.com> writes:
Knud Sørensen wrote:
 On Sat, 04 Nov 2006 10:20:37 +0200, Lionello Lunesu wrote:
 
 Walter Bright wrote:
 Knud Sørensen wrote:
 Will something like this be possible ??

 tuple t=(7, 'a', 6.8);

  print t; // for print(7, 'a', 6.8)

print(t);

and very consistent with the way functions are called. For example print(7,'a',6.8) passes to tuple (7,'a',6.8) to the function print. L.

Did you mean like this. tuple t=7,'a',6.8; print(t);

Yes, possible needing the () to prevent ambiguity with declaration of multiple variables.
Nov 05 2006
prev sibling parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Oskar Linde wrote:

 As I said, I think this looks great. We are no longer in the vicinity of D
 1.0... We are already at 2.0 :)

GDC is still at 0.9 though, so it will be a while before it is portable. --anders
Nov 02 2006
prev sibling next sibling parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Walter Bright wrote:
 See http://www.digitalmars.com/d/variadic-function-templates.html
 
 Why now? Because it's such a pain to do template programming without 
 them, and because I wanted to have a good signals and slots 
 implementation. That was the last piece needed to make S&S work right 
 (unless I'm way off track with it).
 
 There's a lot of unexplored territory with the tuples, they should be 
 able to do a lot more than the current rather limited ability.

This is great! I've already thought of a number of ways to vastly improve the metaprogramming stuff I'm using in Pyd. (Sigh... and I just re-wrote all of that once already.) Pyd is a great use-case for an MPL, and I've been compiling a pretty decent one while writing it (with great work from h3r3tic and Don and others). I think it's about to get a whole lot more interesting... -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Nov 02 2006
parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Kirk McDonald wrote:
 Walter Bright wrote:
 See http://www.digitalmars.com/d/variadic-function-templates.html

 Why now? Because it's such a pain to do template programming without 
 them, and because I wanted to have a good signals and slots 
 implementation. That was the last piece needed to make S&S work right 
 (unless I'm way off track with it).

 There's a lot of unexplored territory with the tuples, they should be 
 able to do a lot more than the current rather limited ability.

This is great! I've already thought of a number of ways to vastly improve the metaprogramming stuff I'm using in Pyd. (Sigh... and I just re-wrote all of that once already.) Pyd is a great use-case for an MPL, and I've been compiling a pretty decent one while writing it (with great work from h3r3tic and Don and others). I think it's about to get a whole lot more interesting...

In trying to work with the variadic templates, I've discovered a few weaknesses and bugs. 1) Index in static foreach is not const Take this template function: void foo(T ...)(T t) { foreach (i, arg; t) { t[i] = something_else; } }
dmd test

Tuples can only be indexed by const (compile-time) index values. The index form of foreach results in runtime indexes. This inconsistency prevents the user from altering the tuple from inside a loop. This prevents some exceedingly useful constructions. Just as good would be the ability to declare "arg" as inout, as in: void foo(T ...)(T t) { foreach (inout arg; t) { arg = something_else; } } DMD currently barfs on this. 2) Tuple aliasing is buggy I'll let the example speak for itself. template Foo(T ...) { alias T Foo; } void func(T ...)(T t) { foreach (arg; t) { writefln(arg); } } void main() { alias Foo!(int, real, char[]) F; func!(F)(12, 3.8, "hello"); }
dmd test2

abnormal program termination I had other complaints, but these are the only ones that occur to me at the moment. -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Nov 02 2006
prev sibling next sibling parent reply Mike Parker <aldacron71 yahoo.com> writes:
Walter Bright wrote:
 See http://www.digitalmars.com/d/variadic-function-templates.html
 
 Why now? Because it's such a pain to do template programming without 
 them, and because I wanted to have a good signals and slots 
 implementation. That was the last piece needed to make S&S work right 
 (unless I'm way off track with it).
 
 There's a lot of unexplored territory with the tuples, they should be 
 able to do a lot more than the current rather limited ability.

Is it possible to restrict use type specialization to restrict a tuple to a specific type? I'm no template guru, but the things I've been toying around with don't work and I don't see anything in the docs about it.
Nov 02 2006
next sibling parent Walter Bright <newshound digitalmars.com> writes:
Mike Parker wrote:
 Is it possible to restrict use type specialization to restrict a tuple 
 to a specific type?

Currently, no. I was reluctant to go down that path until I know where it leads.
Nov 02 2006
prev sibling parent reply Carlos Santander <csantander619 gmail.com> writes:
Mike Parker escribió:
 Walter Bright wrote:
 See http://www.digitalmars.com/d/variadic-function-templates.html

 Why now? Because it's such a pain to do template programming without 
 them, and because I wanted to have a good signals and slots 
 implementation. That was the last piece needed to make S&S work right 
 (unless I'm way off track with it).

 There's a lot of unexplored territory with the tuples, they should be 
 able to do a lot more than the current rather limited ability.

Is it possible to restrict use type specialization to restrict a tuple to a specific type? I'm no template guru, but the things I've been toying around with don't work and I don't see anything in the docs about it.

Is that really needed? Forgive the syntax, but wouldn't this work? void foo (T) (T [] args ...) { ... } -- Carlos Santander Bernal
Nov 02 2006
parent Walter Bright <newshound digitalmars.com> writes:
Carlos Santander wrote:
 
 Is that really needed? Forgive the syntax, but wouldn't this work?
 
 void foo (T) (T [] args ...)
 {
     ...
 }

It might, but I want to see if we can get by without it first.
Nov 02 2006
prev sibling next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Walter Bright wrote:
 See http://www.digitalmars.com/d/variadic-function-templates.html
 
 Why now? Because it's such a pain to do template programming without 
 them, and because I wanted to have a good signals and slots 
 implementation. That was the last piece needed to make S&S work right 
 (unless I'm way off track with it).
 
 There's a lot of unexplored territory with the tuples, they should be 
 able to do a lot more than the current rather limited ability.

Perhaps boost fusion is one example where this territory is explored. I'm very curious to see what some D programmers will do with this. Two minor mistakes in the examples from http://www.digitalmars.com/d/template.html: Write!(int, char, double).print(1, 'a', 6.8); // prints: args are 1a6.8 should be: Write!(int, char, double).write(1, 'a', 6.8); And: void Foo(T t, R r) { writefln(t); if (r.length) // if more arguments Foo(r); // do the rest of the arguments } should be: void Foo(T t, R r) { writefln(t); static if (r.length)// if more arguments Foo(r); // do the rest of the arguments }
Nov 02 2006
parent Walter Bright <newshound digitalmars.com> writes:
Fixed. Thanks.
Nov 02 2006
prev sibling next sibling parent reply nazo <lovesyao gmail.com> writes:
hi,
I found some bugs.

void Foo(R...)(R r){
   writefln(R.length);
   writefln(r.length);
//  R[0] t;//faild
   typeof(r[0]) t;
   static if(r.length>1)
     Foo(r[1..$]);
}

R Bar(R...)(R r){
   return r;
}

void main(){
     Foo(1, 'a', 6.8);
//    writefln(Bar(1, 'a', 6.8));//faild
}
Nov 02 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
nazo wrote:
 hi,
 I found some bugs.
 
 void Foo(R...)(R r){
   writefln(R.length);
   writefln(r.length);
 //  R[0] t;//faild
   typeof(r[0]) t;
   static if(r.length>1)
     Foo(r[1..$]);
 }
 
 R Bar(R...)(R r){
   return r;
 }
 
 void main(){
     Foo(1, 'a', 6.8);
 //    writefln(Bar(1, 'a', 6.8));//faild
 }

Tuples don't currently work as return types.
Nov 02 2006
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Walter Bright wrote:
 nazo wrote:
 hi,
 I found some bugs.

 void Foo(R...)(R r){
   writefln(R.length);
   writefln(r.length);
 //  R[0] t;//faild
   typeof(r[0]) t;
   static if(r.length>1)
     Foo(r[1..$]);
 }

 R Bar(R...)(R r){
   return r;
 }

 void main(){
     Foo(1, 'a', 6.8);
 //    writefln(Bar(1, 'a', 6.8));//faild
 }

Tuples don't currently work as return types.

.. nor could they as they are not types in the first place. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Nov 05 2006
prev sibling next sibling parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Walter Bright wrote:
 See http://www.digitalmars.com/d/variadic-function-templates.html
 
 Why now? Because it's such a pain to do template programming without 
 them, and because I wanted to have a good signals and slots 
 implementation. That was the last piece needed to make S&S work right 
 (unless I'm way off track with it).
 
 There's a lot of unexplored territory with the tuples, they should be 
 able to do a lot more than the current rather limited ability.

I'm glad you could get that to work! But why not force "static" before the "foreach"? L.
Nov 02 2006
parent Sean Kelly <sean f4.ca> writes:
Lionello Lunesu wrote:
 Walter Bright wrote:
 See http://www.digitalmars.com/d/variadic-function-templates.html

 Why now? Because it's such a pain to do template programming without 
 them, and because I wanted to have a good signals and slots 
 implementation. That was the last piece needed to make S&S work right 
 (unless I'm way off track with it).

 There's a lot of unexplored territory with the tuples, they should be 
 able to do a lot more than the current rather limited ability.

I'm glad you could get that to work! But why not force "static" before the "foreach"?

Because 'a' is a run-time construct. It's a bit weird, but think of tuples (ie. variadric templates) like static arrays. You know their length and element types at compile-time and so can use static if, etc, for processing some bits then. But they are also a run-time construct in that actual data is being passed around, so iterating across the data uses foreach. That said, it would be kind of nice to have static foreach work on the contents of static arrays, tuples containing constants, type lists, etc. This could make creating factory classes extremely simple. Sean
Nov 02 2006
prev sibling next sibling parent reply BCS <BCS pathlink.com> writes:
Walter Bright wrote:
 See http://www.digitalmars.com/d/variadic-function-templates.html
 
 Why now? Because it's such a pain to do template programming without 
 them, and because I wanted to have a good signals and slots 
 implementation. That was the last piece needed to make S&S work right 
 (unless I'm way off track with it).
 
 There's a lot of unexplored territory with the tuples, they should be 
 able to do a lot more than the current rather limited ability.

Ooohhh! Wow! Neat stuff! Tuples look cool, particularly with the "static" foreach on them. Is there any way to convert a struct/class into a tuple? It would allow something like this: // byte swap every member of each argument template ByteSwap(T, A...) { void ByteSwap(inout T t, inout A a) { ByteSwap(t); foreach(t; a) ByteSwap(t); } } template ByteSwap(A) { void ByteSwap(inout A a) { static if(is(a : Object)) // form tuple from members ByteSwap(a[0].*); else LowLevelByteSwap(a[0].*); } }
Nov 02 2006
parent Walter Bright <newshound digitalmars.com> writes:
BCS wrote:
 Ooohhh! Wow! Neat stuff! Tuples look cool, particularly with the 
 "static" foreach on them. Is there any way to convert a struct/class 
 into a tuple? It would allow something like this:

That does look pretty cool!
Nov 02 2006
prev sibling next sibling parent reply "Craig Black" <cblack ara.com> writes:
This feature seems to supercede older versions of variadic functions.  Are 
there still reasons to use the older approach to variadics?  If not, should 
any of the older approaches ever be deprecated in order to simplify the D 
language?

-Craig 
Nov 02 2006
next sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Craig Black wrote:
 This feature seems to supercede older versions of variadic functions.  Are 
 there still reasons to use the older approach to variadics?  If not, should 
 any of the older approaches ever be deprecated in order to simplify the D 
 language?

That's a very good question, and I don't know the answer. writefln()'s current implementation may be obsolete. But it's premature to write its obituary. Let's see how things unfold a bit first.
Nov 02 2006
next sibling parent reply Benji Smith <dlanguage benjismith.net> writes:
Craig Black wrote:
 This feature seems to supercede older versions of variadic functions.
 Are there still reasons to use the older approach to variadics?


Walter Bright wrote:
 That's a very good question, and I don't know the answer. writefln()'s 
 current implementation may be obsolete. But it's premature to write its 
 obituary. Let's see how things unfold a bit first.

I'd hate to think that every call to a variadic function would require a template instantiation. Doesn't seem like it'd be very efficient. --benji
Nov 02 2006
parent reply Kyle Furlong <kylefurlong gmail.com> writes:
Benji Smith wrote:
 Craig Black wrote:
  >> This feature seems to supercede older versions of variadic functions.
  >> Are there still reasons to use the older approach to variadics?
 
 Walter Bright wrote:
 That's a very good question, and I don't know the answer. writefln()'s 
 current implementation may be obsolete. But it's premature to write 
 its obituary. Let's see how things unfold a bit first.

I'd hate to think that every call to a variadic function would require a template instantiation. Doesn't seem like it'd be very efficient. --benji

Wait, templating function calls incurs a runtime penalty?
Nov 02 2006
next sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Kyle Furlong wrote:
 Wait, templating function calls incurs a runtime penalty?

Nope, but we wouldn't like to #include "C++CompileTimes.hpp"
Nov 02 2006
next sibling parent Kyle Furlong <kylefurlong gmail.com> writes:
Tom S wrote:
 Kyle Furlong wrote:
 Wait, templating function calls incurs a runtime penalty?

Nope, but we wouldn't like to #include "C++CompileTimes.hpp"

For me, if I can get a 2:1 speedup in compiletime:runtime, thats a very good thing.
Nov 02 2006
prev sibling parent clayasaurus <clayasaurus gmail.com> writes:
Tom S wrote:
 Kyle Furlong wrote:
 Wait, templating function calls incurs a runtime penalty?

Nope, but we wouldn't like to #include "C++CompileTimes.hpp"

One of the things I like about D are the fast compile times, I'd hate to see that change.
Nov 03 2006
prev sibling parent BCS <BCS pathlink.com> writes:
Kyle Furlong wrote:
 Benji Smith wrote:
 
 Craig Black wrote:
  >> This feature seems to supercede older versions of variadic functions.
  >> Are there still reasons to use the older approach to variadics?

 Walter Bright wrote:

 That's a very good question, and I don't know the answer. 
 writefln()'s current implementation may be obsolete. But it's 
 premature to write its obituary. Let's see how things unfold a bit 
 first.

I'd hate to think that every call to a variadic function would require a template instantiation. Doesn't seem like it'd be very efficient. --benji

Wait, templating function calls incurs a runtime penalty?

To some extent, yes. having templated function increases the memory footprint and working set of the program and can cause more swapping and cash misses. Another problem with deprecating varidic function would be the template varidic functions have different types: <code> // silly example void function(...) printer; if(hasEOL) printer = &writef; else printer = &writefln; printer("the first thing is: %s", GetString()); printer("the second thing is: %s", GetOtherString()); </code> The problem is that template varidics operate at compile time, not run time.
Nov 03 2006
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
Walter Bright wrote:
 Craig Black wrote:
 
 This feature seems to supercede older versions of variadic functions.  
 Are there still reasons to use the older approach to variadics?  If 
 not, should any of the older approaches ever be deprecated in order to 
 simplify the D language?

That's a very good question, and I don't know the answer. writefln()'s current implementation may be obsolete. But it's premature to write its obituary. Let's see how things unfold a bit first.

Definitely too early to kill runtime variadics just because there are now compile time ones. writefln is an especially good example of why not. In a stdio heavy app it can get called in thousands of different ways with different combination of argument types. Do you really want each of those to be a separately instantiated function? It may run slightly faster but the code size will be huge. No, writefln definitely still has a place as-is. --bb
Nov 02 2006
prev sibling parent reply Reiner Pope <reiner.pope REMOVE.THIS.gmail.com> writes:
Craig Black wrote:
 This feature seems to supercede older versions of variadic functions.  Are 
 there still reasons to use the older approach to variadics?  If not, should 
 any of the older approaches ever be deprecated in order to simplify the D 
 language?
 
 -Craig 
 
 

The only feature-wise differences I can see between old varargs and new variadic templates is that old varargs can be done without the source-code present, and old varargs can be a virtual function of a class. We can address both of these concerns with wrapper functions and an additional Phobos library: // This would be part of Phobos struct varargData { TypeInfo[] ti; void* argptr; } varargData getVarargData(T...) (T t) { varargData info; with (info) foreach (t; a) { ti ~= typeid(t); argptr ~= cast(void*)t[0..t.sizeof]; // I'm not sure if this is right, but you get the idea } return info; } // This would be the wrapper function of the closed-source library. // The wrapper is open source, but doesn't expose any algorithmic details. // This is analogous to C++ header files. void opensourceWrapper(T...) (T t) { auto data = getVarargData(t); closedFoo(data); } // We could create a 'final' wrapper function within a class: class Foo { final void foo(T...) (T t) { auto data = getVarargData(t); virtualFoo(data); } // Subclasses override this void virtualFoo(varargData data) {...} } So, the same functionality as old varargs can be achieved with new varargs, with a small pattern on the declaration site. I assert that the need for this pattern will be sufficiently small (since vararg functions are quite rare, and they are generally better to implement with templates anyway) that this syntactic sugar (old varargs) can be removed from the language. Furthermore, this pattern is simple enough that it should be possible to express with a sufficiently powerful macro system. Unfortunately, the lack of string pasting in macros means that making differently-named wrappers is not possible at the moment. Cheers, Reiner
Nov 02 2006
parent reply Bill Baxter <wbaxter gmail.com> writes:
Reiner Pope wrote:
 Craig Black wrote:
 
 This feature seems to supercede older versions of variadic functions.  
 Are there still reasons to use the older approach to variadics?  If 
 not, should any of the older approaches ever be deprecated in order to 
 simplify the D language?

 -Craig

The only feature-wise differences I can see between old varargs and new variadic templates is that old varargs can be done without the source-code present, and old varargs can be a virtual function of a class. We can address both of these concerns with wrapper functions and an additional Phobos library: // This would be part of Phobos struct varargData { TypeInfo[] ti; void* argptr; } varargData getVarargData(T...) (T t) { varargData info; with (info) foreach (t; a) { ti ~= typeid(t); argptr ~= cast(void*)t[0..t.sizeof]; // I'm not sure if this is right, but you get the idea } return info; } // This would be the wrapper function of the closed-source library. // The wrapper is open source, but doesn't expose any algorithmic details. // This is analogous to C++ header files. void opensourceWrapper(T...) (T t) { auto data = getVarargData(t); closedFoo(data); } // We could create a 'final' wrapper function within a class: class Foo { final void foo(T...) (T t) { auto data = getVarargData(t); virtualFoo(data); } // Subclasses override this void virtualFoo(varargData data) {...} } So, the same functionality as old varargs can be achieved with new varargs, with a small pattern on the declaration site. I assert that the need for this pattern will be sufficiently small (since vararg functions are quite rare, and they are generally better to implement with templates anyway) that this syntactic sugar (old varargs) can be removed from the language. Furthermore, this pattern is simple enough that it should be possible to express with a sufficiently powerful macro system. Unfortunately, the lack of string pasting in macros means that making differently-named wrappers is not possible at the moment. Cheers, Reiner

Does that handle a variadic function in an interface, too? interface ILogger { void log_msg(char[] fmt, ...); } --bb
Nov 03 2006
parent Reiner Pope <reiner.pope REMOVE.THIS.gmail.com> writes:
 Does that handle a variadic function in an interface, too?
 
 interface ILogger
 {
   void log_msg(char[] fmt, ...);
 }
 
 --bb

No, I don't think it does. You could get away with this, though: interface ILogger { void log_msg_impl(char[] fmt, varargData data); } void log_msg(T...) (ILogger logger, char[] fmt, T t) { auto data = getVarargData(t); logger.log_msg_impl(fmt, data); } If the implicit-this syntax sugar we have for arrays (which allows "foo".toupper) was allowed for all types, then this discrepancy would disappear, and you could write the call as if were a member function: myLogger.log_msg("foo: %d", foo); as opposed to log_msg(myLogger, "foo: %d", foo); Cheers, Reiner
Nov 03 2006
prev sibling next sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Walter Bright wrote:
 See http://www.digitalmars.com/d/variadic-function-templates.html
 
 Why now? Because it's such a pain to do template programming without 
 them, and because I wanted to have a good signals and slots 
 implementation. That was the last piece needed to make S&S work right 
 (unless I'm way off track with it).
 
 There's a lot of unexplored territory with the tuples, they should be 
 able to do a lot more than the current rather limited ability.

Cool, it really quite helps the (many) template code out there that had to replicate code for each number of parameters it wanted to support. Also, tuples are quite a good framework to implement compile-time reflection upon. For example, something more or less like this: struct Foo { int x, y; void func(int a) {} } ... foo = new Foo(); // Then any kind of aggregate has a membersTuple property where // each membersTuple element is an alias to the member foo.membersTuple[0]++; //foo.membersTuple[0] same as foo.x foo.membersTuple[1]--; //foo.membersTuple[1] same as foo.y foo.membersTuple[2](42); //foo.membersTuple[2] same as foo.func Then we could have generic serializers (and other stuff) like: template serialize( TYPE ) { void serialize(TYPE t ) { foreach(member; t.membersTuple) { // Check to see if the member is a field // and not a method or an inner type: static if( !is(member) && !is(member == function) ) { writeln("member: ", typeid(typeof(member)), " value: ", member); } } } } -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Nov 05 2006
prev sibling parent reply rm <roel.mathys gmail.com> writes:
should this work:




template Templ(T, R ...) { static if (R.length) { const char [] s = "yes"; // writefln(s); } else { const char [] s = "no"; // writefln(s); } } void main() { mixin Templ!(int,char); writefln(s); // can't put this into the template } <<< It compiles, it runs fine, but I'm not using function templates. otoh, try to bring the lines commented out into play, it won't compile anymore. bye, roel
Nov 07 2006
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
rm wrote:
 
 should this work:
 



template Templ(T, R ...) { static if (R.length) { const char [] s = "yes"; // writefln(s); } else { const char [] s = "no"; // writefln(s); } } void main() { mixin Templ!(int,char); writefln(s); // can't put this into the template } <<< It compiles, it runs fine, but I'm not using function templates. otoh, try to bring the lines commented out into play, it won't compile anymore. bye, roel

That's because you can't have executable statements in a template. I really wish you could, tho. If you want to write those out at COMPILE TIME, however, you can change
 writefln(s);

To:
 pragma(msg, s);

-- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Nov 07 2006