Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1428

Show
Ignore:
Timestamp:
02/19/10 03:14:19 (15 years ago)
Author:
dsimcha
Message:

Added toDelegate.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/std/functional.d

    r1279 r1428  
    506506     
    507507    // assert(compose!(baz, `to!(int)(a) + 1`, foo)(1) == 2.5); 
    508508    // assert(compose!(baz, bar)("1"[]) == 2.5); 
    509509     
    510510    // @@@BUG@@@ 
    511511    //assert(compose!(baz, bar)("1") == 2.5); 
    512512 
    513513    // @@@BUG@@@ 
    514514    //assert(compose!(`a + 0.5`, `to!(int)(a) + 1`, foo)(1) == 2.5); 
    515515} 
     516 
     517private struct DelegateFaker(R, Args...) { 
     518    R doIt(Args args) { 
     519        // When this function gets called, the this pointer isn't really a 
     520        // this pointer (no instance even really exists), but a function 
     521        // pointer that points to the function 
     522        // to be called.  Cast it to the correct type and call it. 
     523 
     524        auto fp = cast(R function(Args)) &this; 
     525        return fp(args); 
     526    } 
     527} 
     528 
     529/**Convert a function pointer to a delegate with the same parameter list and 
     530 * return type, avoiding heap allocations and use of auxiliary storage. 
     531 * 
     532 * Examples: 
     533 * --- 
     534 * void doStuff() { 
     535 *     writeln("Hello, world."); 
     536 * } 
     537 * 
     538 * void runDelegate(void delegate() myDelegate) { 
     539 *     myDelegate(); 
     540 * } 
     541 * 
     542 * auto delegateToPass = toDelegate(&doStuff); 
     543 * runDelegate(delegateToPass);  // Calls doStuff, prints "Hello, world." 
     544 * --- 
     545 * 
     546 * Bugs:  Doesn't work properly with ref return.  (See DMD bug 3756.) 
     547 */ 
     548auto toDelegate(F)(F fp) { 
     549 
     550    // Workaround for DMD Bug 1818. 
     551    mixin("alias " ~ ReturnType!(F).stringof ~ 
     552        " delegate" ~ ParameterTypeTuple!(F).stringof ~ " DelType;"); 
     553 
     554    version(none) { 
     555        // What the code would be if it weren't for bug 1818: 
     556        alias ReturnType!(F) delegate(ParameterTypeTuple!(F)) DelType; 
     557    } 
     558 
     559    static struct DelegateFields { 
     560        union { 
     561            DelType del; 
     562            pragma(msg, typeof(del)); 
     563 
     564            struct { 
     565                void* contextPtr; 
     566                void* funcPtr; 
     567            } 
     568        } 
     569    } 
     570 
     571    // fp is stored in the returned delegate's context pointer.  The returned 
     572    // delegate's function pointer points to DelegateFaker.doIt. 
     573    DelegateFields df; 
     574    df.contextPtr = cast(void*) fp; 
     575 
     576    DelegateFaker!(ReturnType!(F), ParameterTypeTuple!(F)) dummy; 
     577    auto dummyDel = &(dummy.doIt); 
     578    df.funcPtr = dummyDel.funcptr; 
     579 
     580    return df.del; 
     581} 
     582 
     583unittest { 
     584    static int inc(ref uint num) { 
     585        num++; 
     586        return 8675309; 
     587    } 
     588 
     589    uint myNum = 0; 
     590    auto incMyNumDel = toDelegate(&inc); 
     591    static assert(is(typeof(incMyNumDel) == int delegate(ref uint))); 
     592    auto returnVal = incMyNumDel(myNum); 
     593    assert(myNum == 1); 
     594}