www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Question: What is the most elegant way to do this:

reply Frank Fischer <frank.fischer s2001.tu-chemnitz.de> writes:

I want to write a template-function in the following way:

void func(T)(T x) {
    static if (is(T : TypeA)) {
        /* do CODE1 with x */
    else {
        TypeA _x = cast(TypeA)x;
        if (x !is null) {
            /* do CODE1 with _x */
        else {
            /* do CODE2 with x */

The function 'func' should check if T is of type TypeA (or a subclass). If
this is the case, CODE1 should be applied to x. If this is not the case,
the function tries to dynamic-cast x to TypeA. If successful, apply CODE1
to _x, otherwise do something different.

It is important for me, that no dynamic-cast is tried if T is of type TypeA.
Furthermore I'd like to have a general (meta-programming?) tool to do this
pattern in various functions.

As an extension, it would be cool if the test can be done on an arbitrary
number of arguments of the function. Furthermore it should be possible, to
do this check againt more than one type, i.e. first do the static test
against TypeA then TypeB and so on and if all those tests fail, do the
dynamic-cast-test. If x is of TypeA (static or dynamic) apply CODE1, if
it's of TypeB apply CODE2, ...

What would be the cleverest way to do this? Of course, CODE1 (for example)
should be there only once and it would be nice if it's not necessary to
write more than one function (i.e. everything necessary, beside the
meta-programming-stuff, should be written in the body of 'func').

Aug 10 2007
parent reply Daniel919 <Daniel919 web.de> writes:
Hi, I attached my solution.

Best regards,
Aug 10 2007
next sibling parent Frank Fischer <frank.fischer s2001.tu-chemnitz.de> writes:
Daniel919 wrote:

 Hi, I attached my solution.
Nice one. Is it possible *not* to use delegates? This is just because of efficiency, since it seems that the use of delegates always generates 'call'-statements in the assembly code (although this may not be a problem in my case). But I really like your solution, it's better than mine, thanks. Frank
Aug 10 2007
prev sibling parent BCS <ao pathlink.com> writes:

I=20guess=20that=20works=2e=20(<delets=20file>=20Excuse=20my=20while=20I=20autoclave=20my=20computer)=2e how=20abou=20this: |import=20std=2estdio; | |template=20check(T=2e=2e=2e) |{ |=20=20void=20check(Tx)(Tx=20x,=20void=20delegate()[]=20dg=20=2e=2e=2e) |=20=20{ |=20=20=20=20static=20if=20(is(Tx=20=3d=3d=20T[0])) |=20=20=20=20{ |=20=20=20=20=20=20dg[0](); |=20=20=20=20} |=20=20=20=20else |=20=20=20=20{ |=20=20=20=20=20=20foreach(i,=20Ts;=20T[1=2e=2e$]) |=20=20=20=20=20=20{ |=20=20=20=20=20=20=20=20if=20(cast(T[i])x=20!is=20null) |=20=20=20=20=20=20=20=20{ |=20=20=20=20=20=20=20=20=20=20dg[i](); |=20=20=20=20=20=20=20=20=20=20return; |=20=20=20=20=20=20=20=20} |=20=20=20=20=20=20=20=20throw=20new=20Exception("cast=20error"); |=20=20=20=20=20=20} |=20=20=20=20} |=20=20} |} | |class=20TypeA0=20{=20int=20id=20=3d=2010;=20} |class=20TypeA=20:=20TypeA0=20{=20int=20id=20=3d=2011;=20} |class=20TypeA2=20:=20TypeA=20{=20int=20id=20=3d=2012;=20} |class=20TypeB=20{=20int=20id=20=3d=2020;=20} | |void=20main() |{ |=20=20auto=20x=20=3d=20new=20TypeA; |=20=20check!(TypeA,=20TypeB)(x,=20{writefln("TypeA=20id=3d%s",=20x=2eid);},=20{writefln("TypeB=20id=3d%s",=20x=2eid);}); |}
Aug 10 2007