On 21.07.2010 23:16, Andrei Alexandrescu wrote:
I compiled and ran the tests myself with -O -release -inline and got 1.95s for Dmitry's implementation and 1.55s for bearophile's.

I optimized Dmitry's implementation in two ways: I replaced the call to clear() with a straight call to the destructor and added = void in two places to avoid double initialization. I got 1.11s, which significantly undercuts the implementation using scope.

Here's the code I used for testing:

struct Scoped(T) {
    ubyte[__traits(classInstanceSize, Test)] _payload = void;
    T getPayload(){
        return cast(T)(_payload.ptr);
    }
    alias getPayload this;

    static Scoped opCall(Args...)(Args args)
    if (is(typeof(T.init.__ctor(args)))) {
        // TODO: should also provide decent error message
        Scoped!T s = void;
        emplace!T(cast(void[])s._payload,args);
        return s;
    }
    ~this() {
        static if (is(typeof(getPayload.__dtor()))) {
            getPayload.__dtor();
        }
    }
}
Thanks for kind feedback (and showing some optimization tricks). Also this implementation still has issues with it: it calls dtor twice. Not a good trait for RAII technique ! :) Since it's now considered useful I feel myself obliged to enhance and correct it. Sadly enough I still haven't managed to apply an inner template trick.
Here's the end result along with a simple unittest:

struct Scoped(T){
    ubyte[__traits(classInstanceSize, T)] _scopedPayload = void;
    T getScopedPayload(){
        return cast(T)(_scopedPayload.ptr);
    }
    alias getScopedPayload this;
    this(Args...)(Args args){
        static if (!is(typeof(getScopedPayload.__ctor(args)))) {
            static assert(false,"Scoped: wrong arguments passed to ctor");
        }else {
            emplace!T(cast(void[])_scopedPayload,args);
        }
     }
    ~this() {
        static if (is(typeof(getScopedPayload.__dtor()))) {
            getScopedPayload.__dtor();
        }
    }
}
//also track down destruction/construction
class A{
    this(int a){ writeln("A with ",a); }
    this(real r){ writeln("A with ",r); }
    ~this(){ writeln("A destroyed");  }
}

unittest{
    {
        auto a = Scoped!A(42);
    }
    {
        auto b = Scoped!A(5.5);
    }
}

--
Dmitry Olshansky

Reply via email to