Compile time variadic functions
Oskar Linde
oskar.lindeREM at OVEgmail.com
Wed Mar 15 01:25:26 PST 2006
Don Clugston skrev:
> Oskar Linde wrote:
>> struct myFuncImplDummy { mixin decl_vararg_func!(myFuncImpl); }
>> alias myFuncImplDummy.func myFunc;
>>
>> Is there any better way to do the decl_vararg_func and dummy struct
>> thing? An identifier name template parameter type would be awesome* (I
>> would have other uses for that as well).
>
> // Just change the 'func' to decl_vararg_func to take advantage
> // of implicit template name promotion.
> template decl_vararg_func(alias realFunc) {
> template decl_vararg_func(A = Empty, B = Empty, C = Empty, D = Empty,
> E = Empty, F = Empty, G = Empty /*, ...*/) {
> static void decl_vararg_func(A a = A.init, B b = B.init, C c =
> C.init, D d = D.init, E e = E.init, F f = F.init, G g = G.init /*,...*/) {
> realFunc(Tuple(a,b,c,d,e,f,g /*,...*/));
> }
> }
> }
>
> // and there's no need for a mixin.
> alias decl_vararg_func!(funcImpl) myFunc;
Of course. How silly of me :) And it easy to add should support for
optional return values too:
template decl_vararg_func(alias realFunc) {
template decl_vararg_func(A = Empty, B = Empty, C = Empty, D = Empty,
E = Empty, F = Empty, G = Empty /*, ...*/) {
typeof(realFunc(Tuple(A.init,B.init,C.init,D.init,E.init,F.init,G.init
/*,...*/))) decl_vararg_func(A a = A.init, B b = B.init, C c = C.init, D
d = D.init, E e = E.init, F f = F.init, G g = G.init /*,...*/) {
return realFunc(Tuple(a,b,c,d,e,f,g /*,...*/));
}
}
}
>
>
> Which means the best effort so far is:
>
>
> > import variadic;
> >
> > template myFuncImpl(T) {
> > void myFuncImpl(T) {
> > static if (is (T == Empty)) {
> > writefln("Done");
> > } else {
> > writefln("Got argument %s of type %s",args.head,
> > typeid(typeof(args.head)));
> > .myFuncImpl(T.tail); // tail-recurse
> > }
> > }
> > }
> >
> > alias decl_vararg_func!(myFuncImpl) myFunc;
> >
> > void main() {
> > myFunc(1.0,2,3L);
> > myFunc();
> > }
It doesn't get any better than this (unless we get a short hand notation
for function templates).
Static array arguments are still a problem though. Static arrays need
some special handling:
- They are are the only type I know of where !is(T == typeof(T.init))
- They have schizophrenic value/reference semantics. (Behaves as a value
type (declaring space) on declaration, but is a reference type otherwise)
- There is no way (that I know of) to define template specializations
generically for static arrays. (Only for static arrays of a defined
number of elements)
The first can be worked around:
Change the default argument value from T.init to Init!(T):
template Init(T) {
const T Init = void;
}
The second is harder:
struct Container(T) { T element; }
...
Container!(typeof(x)) container;
container.element = x; // Works for all types except static arrays.
Meaning I have to convert static arrays into dynamic arrays:
template Declare(T) { T Declare; }
...
// Convert static arrays types into dynamic array types
template Dynify(T) {
static if (is (typeof(Declare!(T)[0]) E)) // Indexable
static if (is (T : E[])) // Implicitly convertible to dynamic array
alias E[] Dynify;
else
alias T Dynify;
else
alias T Dynify;
}
With those changes:
myFunc("hello",5,2.3);
works. (Attaching the code again)
/Oskar
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: variadic.d
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20060315/7f6dc8ed/attachment.ksh>
More information about the Digitalmars-d
mailing list