On Mon, 19 Jul 2010 22:06:14 +0200, Simen kjaeraas <simen.kja...@gmail.com> wrote:

Rory McGuire <rmcgu...@neonova.co.za> wrote:

Does anyone know how to detect if there is a setter for a property? The
code below prints the same thing for both
the setter and the getter of "front":

==============================
import std.traits;

class Foo {
     uint num;

     @property ref uint front() {
         return num;
     }
     @property void front(uint i) {
         num = i;
     }

     ref uint front2() {
        return num;
     }
}

template isProperty(alias func) if (isCallable!(func)) {
        enum isProperty = (functionAttributes!(func) &
FunctionAttribute.PROPERTY)==0 ? false : true;
}

template hasSetter(alias func) if (isCallable!(func)) {
enum hasSetter = (isProperty!(func) && ParameterTypeTuple!(func).length >
0 && ReturnType!(func).stringof != "void") ? true : false;
}

For what it's worth, I would simply check if the property allows assignment. i.e.:

template hasSetter(alias func) if (isCallable!(func)) {
     enum hasSetter = isProperty!(func) &&
         is( typeof( (){ func = ReturnType!(func).init; } ) );
}


Hehe good solution, never even crossed my mind.
And it doesn't match ref return types such as the following signature.

ref uint front() { return num; }

My test code below:
===================================
import std.traits;

class Foo {
    uint num;

    @property ref uint front() {
        return num;
    }
/+    @property void front(uint i) {
        num = i;
    }+/

    ref uint front2() {return num;}
}

template isProperty(alias func) if (isCallable!(func)) {
enum isProperty = (functionAttributes!(func) & FunctionAttribute.PROPERTY)==0 ? false : true;
}

template hasSetter(alias func) if (isCallable!(func)) {
    enum hasSetter = isProperty!(func) &&
        is( typeof( (){ func = ReturnType!(func).init; } ) );
}

void main() {
    Foo foo;
        pragma(msg, hasSetter!(foo.front)); // is the return type null (setter)
        
        static if (isProperty!(foo.front)) {
                pragma(msg, "property");
        } else {
                pragma(msg, "not a property");
        }

        alias MemberFunctionsTuple!(Foo,"front") fronts;
        foreach (s; fronts) {
                pragma(msg, hasSetter!(s));
        }

}
================================

Could be used in a GUI library for checking which properties of a class are editable and which are only for display.
And tell you about it at compile time.


Thanks!

Reply via email to