digitalmars.D - Variadic templates
- Walter Bright (7/7) Nov 02 2006 See http://www.digitalmars.com/d/variadic-function-templates.html
- Oskar Linde (17/25) Nov 02 2006 This looks excellent. Supporting both a head-tail recursive variant and ...
- Walter Bright (9/22) Nov 02 2006 My current thought is that they will never be types, i.e. you will not
- =?iso-8859-1?q?Knud_S=F8rensen?= (6/35) Nov 02 2006 Will something like this be possible ??
- Walter Bright (4/8) Nov 02 2006 It would be:
- Lionello Lunesu (5/16) Nov 04 2006 What about the comma operator? It would be perfect for creating tuples,
- Walter Bright (8/24) Nov 04 2006 For creating tuples, the following works:
- Jarrett Billingsley (6/13) Nov 04 2006 But:
-
Walter Bright
(2/7)
Nov 05 2006
I'll fix it regardless
. - =?iso-8859-1?q?Knud_S=F8rensen?= (4/22) Nov 04 2006 Did you mean like this.
- Lionello Lunesu (3/25) Nov 05 2006 Yes, possible needing the () to prevent ambiguity with declaration of
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (3/5) Nov 02 2006 GDC is still at 0.9 though, so it will be a while before it is portable.
- Kirk McDonald (11/20) Nov 02 2006 This is great! I've already thought of a number of ways to vastly
- Kirk McDonald (44/64) Nov 02 2006 In trying to work with the variadic templates, I've discovered a few
- Mike Parker (4/13) Nov 02 2006 Is it possible to restrict use type specialization to restrict a tuple
- Walter Bright (3/5) Nov 02 2006 Currently, no. I was reluctant to go down that path until I know where
- Carlos Santander (8/23) Nov 02 2006 Is that really needed? Forgive the syntax, but wouldn't this work?
- Walter Bright (2/9) Nov 02 2006 It might, but I want to see if we can get by without it first.
- Lutger (21/30) Nov 02 2006 Perhaps boost fusion is one example where this territory is explored.
- Walter Bright (1/1) Nov 02 2006 Fixed. Thanks.
- nazo (17/17) Nov 02 2006 hi,
- Walter Bright (2/22) Nov 02 2006 Tuples don't currently work as return types.
- Bruno Medeiros (5/28) Nov 05 2006 .. nor could they as they are not types in the first place.
- Lionello Lunesu (4/13) Nov 02 2006 I'm glad you could get that to work!
- Sean Kelly (11/25) Nov 02 2006 Because 'a' is a run-time construct. It's a bit weird, but think of
- BCS (25/34) Nov 02 2006 Ooohhh! Wow! Neat stuff! Tuples look cool, particularly with the
- Walter Bright (2/5) Nov 02 2006 That does look pretty cool!
- Craig Black (5/5) Nov 02 2006 This feature seems to supercede older versions of variadic functions. A...
- Walter Bright (4/8) Nov 02 2006 That's a very good question, and I don't know the answer. writefln()'s
- Benji Smith (5/10) Nov 02 2006 I'd hate to think that every call to a variadic function would require a...
- Kyle Furlong (2/15) Nov 02 2006 Wait, templating function calls incurs a runtime penalty?
- Tom S (2/3) Nov 02 2006 Nope, but we wouldn't like to #include "C++CompileTimes.hpp"
- Kyle Furlong (3/7) Nov 02 2006 For me, if I can get a 2:1 speedup in compiletime:runtime, thats a very
- clayasaurus (3/7) Nov 03 2006 One of the things I like about D are the fast compile times, I'd hate to...
- BCS (18/39) Nov 03 2006 To some extent, yes. having templated function increases the memory
- Bill Baxter (9/20) Nov 02 2006 Definitely too early to kill runtime variadics just because there are
- Reiner Pope (56/64) Nov 02 2006 I think that we can get rid of old varargs, and here's why:
- Bill Baxter (7/82) Nov 03 2006 Does that handle a variadic function in an interface, too?
- Reiner Pope (18/26) Nov 03 2006 No, I don't think it does. You could get away with this, though:
- Bruno Medeiros (31/40) Nov 05 2006 Cool, it really quite helps the (many) template code out there that had
- rm (23/24) Nov 07 2006 import std.stdio;
- Daniel Keep (11/45) Nov 07 2006 That's because you can't have executable statements in a template. I
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
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
Oskar Linde wrote: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.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) ?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 argumentI'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
On Thu, 02 Nov 2006 02:02:35 -0800, Walter Bright wrote:Oskar Linde wrote:Will something like this be possible ?? tuple t=(7, 'a', 6.8); print t; // for print(7, 'a', 6.8)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.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) ?That's right. Those two declarations are the same thing. A function parameter list is a tuple.Then you could write something like this. print func1 func2 t; // for print(func1(func2(7, 'a', 6.8)));will it be possible to declare a function such as taking a specific tuple argumentI'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
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
Walter Bright wrote:Knud S�rensen wrote: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.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 04 2006
Lionello Lunesu wrote:Walter Bright wrote:For creating tuples, the following works: template Tuple(T...) { alias T Tuple; } alias Tuple!(7, 'a', 6.8) t; print(t);Knud S�rensen wrote: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.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 04 2006
"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
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
On Sat, 04 Nov 2006 10:20:37 +0200, Lionello Lunesu wrote:Walter Bright wrote:Did you mean like this. tuple t=7,'a',6.8; print(t);Knud S�rensen wrote: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.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 04 2006
Knud S�rensen wrote:On Sat, 04 Nov 2006 10:20:37 +0200, Lionello Lunesu wrote:Yes, possible needing the () to prevent ambiguity with declaration of multiple variables.Walter Bright wrote:Did you mean like this. tuple t=7,'a',6.8; print(t);Knud S�rensen wrote: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.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 05 2006
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
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
Kirk McDonald wrote:Walter Bright wrote: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; } }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...dmd testtest.d(35): Integer constant expression expected instead of cast(int)(i) 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 test2Assertion failure: 'global.errors' on line 2752 in file 'template.c' 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
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
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
Mike Parker escribi�:Walter Bright wrote:Is that really needed? Forgive the syntax, but wouldn't this work? void foo (T) (T [] args ...) { ... } -- Carlos Santander BernalSee 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
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
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
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
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
Walter Bright wrote:nazo wrote:.. 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#Dhi, 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 05 2006
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
Lionello Lunesu wrote:Walter Bright wrote: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. SeanSee 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"?
Nov 02 2006
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
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
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
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
Craig Black wrote:Walter Bright wrote:This feature seems to supercede older versions of variadic functions. Are there still reasons to use the older approach to variadics?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
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:Wait, templating function calls incurs a runtime penalty?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
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
Tom S wrote:Kyle Furlong wrote:For me, if I can get a 2:1 speedup in compiletime:runtime, thats a very good thing.Wait, templating function calls incurs a runtime penalty?Nope, but we wouldn't like to #include "C++CompileTimes.hpp"
Nov 02 2006
Tom S wrote:Kyle Furlong wrote:One of the things I like about D are the fast compile times, I'd hate to see that change.Wait, templating function calls incurs a runtime penalty?Nope, but we wouldn't like to #include "C++CompileTimes.hpp"
Nov 03 2006
Kyle Furlong wrote:Benji Smith wrote: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.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:Wait, templating function calls incurs a runtime penalty?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 03 2006
Walter Bright wrote:Craig Black wrote: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. --bbThis 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
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? -CraigI think that we can get rid of old varargs, and here's why: 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
Reiner Pope wrote:Craig Black wrote:Does that handle a variadic function in an interface, too? interface ILogger { void log_msg(char[] fmt, ...); } --bbThis 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? -CraigI think that we can get rid of old varargs, and here's why: 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 03 2006
Does that handle a variadic function in an interface, too? interface ILogger { void log_msg(char[] fmt, ...); } --bbNo, 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
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
should this work:import std.stdio; 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
rm wrote:should this work: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 changeimport std.stdio; 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, roelwritefln(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