Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
July 19, 2010 Detecting a property setter? | ||||
---|---|---|---|---|
| ||||
Attachments: | Hi, 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; } void main() { Foo foo; pragma(msg, hasSetter!(foo.front)); static if (isProperty!(foo.front)) { pragma(msg, "property"); } else { pragma(msg, "not a property"); } alias MemberFunctionsTuple!(Foo,"front") fronts; foreach (s; fronts) { pragma(msg, ReturnType!(s)); // this line just prints "uint" for both "front" properties! } } ============================ Is this a compiler bug? Or am I wrong again? Thanks Rory www.neonova.co.za: http://cf.neonova.co.za/9YXp View: https://mail1.clearformat.com/vcard.php?uid=11&pid=10 Beta Test Advert: http://fwd.clearformat.com/9YXn |
July 19, 2010 Re: Detecting a property setter? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Rory McGuire | Rory McGuire <rmcguire@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; } ) ); } -- Simen |
July 19, 2010 Re: Detecting a property setter? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen kjaeraas Attachments:
| On Mon, Jul 19, 2010 at 22:06, Simen kjaeraas <simen.kjaras@gmail.com>wrote:
> template hasSetter(alias func) if (isCallable!(func)) {
> enum hasSetter = isProperty!(func) &&
> is( typeof( (){ func = ReturnType!(func).init; } ) );
> }
>
>
In that case, for the second func, the one you call ReturnType on, how does
the compiler knows it must take the ref uint one (the getter) and not the
void func() one?
Philippe
|
July 19, 2010 Re: Detecting a property setter? | ||||
---|---|---|---|---|
| ||||
On Monday, July 19, 2010 13:42:51 Philippe Sigaud wrote:
> On Mon, Jul 19, 2010 at 22:06, Simen kjaeraas <simen.kjaras@gmail.com>wrote:
> > template hasSetter(alias func) if (isCallable!(func)) {
> >
> > enum hasSetter = isProperty!(func) &&
> >
> > is( typeof( (){ func = ReturnType!(func).init; } ) );
> >
> > }
>
> In that case, for the second func, the one you call ReturnType on, how does
> the compiler knows it must take the ref uint one (the getter) and not the
> void func() one?
>
>
> Philippe
I don't think that you're supposed to be able to have a getter property returning a ref at the same time that you have a setter property with the same name. It certainly sounds like it should be a bug in any case.
- Jonathan M Davis
|
July 19, 2010 Re: Detecting a property setter? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen kjaeraas | On Mon, 19 Jul 2010 22:06:14 +0200, Simen kjaeraas <simen.kjaras@gmail.com> wrote: > Rory McGuire <rmcguire@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! |
July 19, 2010 Re: Detecting a property setter? | ||||
---|---|---|---|---|
| ||||
On Mon, 19 Jul 2010 23:25:01 +0200, Jonathan M Davis <jmdavisprog@gmail.com> wrote:
> On Monday, July 19, 2010 13:42:51 Philippe Sigaud wrote:
>> On Mon, Jul 19, 2010 at 22:06, Simen kjaeraas <simen.kjaras@gmail.com>wrote:
>> > template hasSetter(alias func) if (isCallable!(func)) {
>> >
>> > enum hasSetter = isProperty!(func) &&
>> >
>> > is( typeof( (){ func = ReturnType!(func).init; } ) );
>> >
>> > }
>>
>> In that case, for the second func, the one you call ReturnType on, how does
>> the compiler knows it must take the ref uint one (the getter) and not the
>> void func() one?
>>
>>
>> Philippe
>
> I don't think that you're supposed to be able to have a getter property
> returning a ref at the same time that you have a setter property with the same
> name. It certainly sounds like it should be a bug in any case.
>
> - Jonathan M Davis
I suppose it would be seen as a bug because it possibly circumvents the getter/setter
philosophy (If you return the internal value anyway).
|
July 19, 2010 Re: Detecting a property setter? | ||||
---|---|---|---|---|
| ||||
Attachments:
| On Mon, 19 Jul 2010 22:42:51 +0200, Philippe Sigaud <philippe.sigaud@gmail.com> wrote:
> On Mon, Jul 19, 2010 at 22:06, Simen kjaeraas <simen.kjaras@gmail.com> wrote:
>> template hasSetter(alias func) if (isCallable!(func)) {
>> enum hasSetter = isProperty!(func) &&
>> is( typeof( (){ func = ReturnType!(func).init; } ) );
>> }
>>
>
> In that case, for the second func, the one you call ReturnType on, how does the compiler knows it must take the ref uint one (the getter) and
> >not the void func() one?
>
>
> Philippe
>
>
Simen is using the fact that the compiler already has to figure out if
there is an overload that matches the requirements. So it ends up
taking the only one that works. Since it seems to ignore the ref return
type property, the property that takes an uint argument must have a
higher precedence (gets checked if it works first).
I wonder if its because Walter probably implemented function overloading
before properties and ref return types. Hopefully its a language
feature and not just a implementation side effect.
-Rory
|
July 19, 2010 Re: Detecting a property setter? | ||||
---|---|---|---|---|
| ||||
On Monday, July 19, 2010 14:37:22 Rory McGuire wrote:
> I suppose it would be seen as a bug because it possibly circumvents the
> getter/setter
> philosophy (If you return the internal value anyway).
No, the problem is that you have _both_ a getter returning a ref and a setter. So, which does the compiler use? Returning a ref isn't a problem - phobos does it with ranges. Doing that, you basically user the getter for setting the property also. However, with both a getter returning a ref and a setter, then the compiler is going to have to choose which to use if you use the property as a setter. It's an ambiguity and thus shouldn't compile. If it does, then that's a bug.
- Jonathan M Davis
|
Copyright © 1999-2021 by the D Language Foundation