www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Detecting a property setter?

reply "Rory McGuire" <rmcguire neonova.co.za> writes:
Content-Type: multipart/alternative; 
	boundary="----=_Part_27942_32606074.1279568935040"

------=_Part_27942_32606074.1279568935040
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit


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

------=_Part_27942_32606074.1279568935040
Content-Type: text/html; charset="us-ascii"
Content-Transfer-Encoding: 7bit

<html>
<body>
<div id="Headers"><div style="padding: 10px 0pt; background-color: rgb(37, 37,
37); color: rgb(255, 255, 255); font-size: 36px; font-family:
Verdana,Arial,Helvetica,sans-serif,'Trebuchet MS','Times New Roman';"><img
src="cid:logo.jpg 85027972.83801" title="Logo"></div></div><div
id="Body_content"><div style="padding: 5px; font-family:
Arial,Helvetica,sans-serif; font-size: 12px;">
Hi,<br />
<br />
Does anyone know how to detect if there is a setter for a property? The  <br />
code below prints the same thing for both<br />
the setter and the getter of "front":<br />
<br />
==============================<br />
import std.traits;<br />
<br />
class Foo {<br />
     uint num;<br />
<br />
      property ref uint front() {<br />
         return num;<br />
     }<br />
      property void front(uint i) {<br />
         num = i;<br />
     }<br />
<br />
     ref uint front2() {<br />
     	return num;<br />
     }<br />
}<br />
<br />
template isProperty(alias func) if (isCallable!(func)) {<br />
	enum isProperty = (functionAttributes!(func) &  <br />
FunctionAttribute.PROPERTY)==0 ? false : true;<br />
}<br />
<br />
template hasSetter(alias func) if (isCallable!(func)) {<br />
	enum hasSetter = (isProperty!(func) && ParameterTypeTuple!(func).length >  <br
/>
0 && ReturnType!(func).stringof != "void") ? true : false;<br />
}<br />
<br />
void main() {<br />
     Foo foo;<br />
	pragma(msg, hasSetter!(foo.front));<br />
	<br />
	static if (isProperty!(foo.front)) {<br />
		pragma(msg, "property");<br />
	} else {<br />
		pragma(msg, "not a property");<br />
	}<br />
	<br />
	alias MemberFunctionsTuple!(Foo,"front") fronts;<br />
	foreach (s; fronts) {<br />
		pragma(msg, ReturnType!(s)); // this line just prints "uint" for both  <br />
"front" properties!<br />
	}<br />
}<br />
============================<br />
<br />
<br />
Is this a compiler bug? Or am I wrong again?<br />
<br />
Thanks<br />
Rory<br />
</div></div><div id="Signatures"><div style="padding: 3px; background-color:
rgb(238, 235, 230); color: rgb(86, 80, 68); line-height: 15px; font-size: 10px;
font-family: Verdana,Arial,Helvetica,sans-serif;">
<strong>Rory McGuire</strong><br>
R&D<br><br>
Tel : +27 (033) 386 7263<br>
<br />
Cell : +27 (082) 856 3646<br />
<strong>Email</strong>: <a href="mailto:rmcguire neonova.co.za"
style="font-size: 10px; font-family: Verdana,Arial,Helvetica,sans-serif; color:
rgb(86, 80, 68);">rmcguire neonova.co.za</a><br>
<strong>Website</strong>: <a href="http://cf.neonova.co.za/9YXp"
style="font-size: 10px; font-family: Verdana,Arial,Helvetica,sans-serif; color:
rgb(86, 80, 68);">www.neonova.co.za</a><br>
<strong>VCard</strong>: <a
href="https://mail1.clearformat.com/vcard.php?uid=11&pid=10" style="font-size:
10px; font-family: Verdana,Arial,Helvetica,sans-serif; color: rgb(86, 80,
68);">View</a><br>
</div></div><div class="inline_ad"><a href="http://fwd.clearformat.com/9YXn"
target="_blank"><img src="cid:ff2d54b.jpg 1163517217.14931" alt="Beta Test
Advert" border="0" class="inline_img"/></a></div>
<div style="font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px;
color:#999999; padding-top:10px;">
  <div align="justify">This email and its attachments may be confidential and
are intended solely for the use of the individual to whom it is addressed. Any
views or opinions expressed are solely those of the author and do not
necessarily represent those of NeoNova. If you are not the intended recipient
of this email and its attachments, you must take no action based upon them, nor
must you copy or show them to anyone. Please contact the sender if you believe
you have received this email in error.</div>
</div>
</body>
</html>
------=_Part_27942_32606074.1279568935040--
Jul 19 2010
next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
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  

}

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
Jul 19 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--0016e6dd85c6c3248a048bc39ceb
Content-Type: text/plain; charset=ISO-8859-1

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; } ) );
 }

the compiler knows it must take the ref uint one (the getter) and not the void func() one? Philippe --0016e6dd85c6c3248a048bc39ceb Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Mon, Jul 19, 2010 at 22:06, Simen kjaeraas <s= pan dir=3D"ltr">&lt;<a href=3D"mailto:simen.kjaras gmail.com">simen.kjaras = gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style= =3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); p= adding-left: 1ex;"> template hasSetter(alias func) if (isCallable!(func)) {<br><div class=3D"im= "> =A0 =A0enum hasSetter =3D isProperty!(func) &amp;&amp;<br></div> =A0 =A0 =A0 =A0is( typeof( (){ func =3D ReturnType!(func).init; } ) );<br> }<br><br></blockquote><div><br>In that case, for the second func, the one y= ou call ReturnType on, how does the compiler knows it must take the ref uin= t one (the getter) and not the void func() one?<br><br><br>Philippe<br> <br><br></div></div> --0016e6dd85c6c3248a048bc39ceb--
Jul 19 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisprog gmail.com> writes:
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
Jul 19 2010
prev sibling next sibling parent "Rory McGuire" <rmcguire neonova.co.za> writes:
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!
Jul 19 2010
prev sibling next sibling parent "Rory McGuire" <rmcguire neonova.co.za> writes:
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).
Jul 19 2010
prev sibling next sibling parent "Rory McGuire" <rmcguire neonova.co.za> writes:
------------WwIskSykX71KN2sh2BqKMU
Content-Type: text/plain; charset=utf-8; format=flowed; delsp=yes
Content-Transfer-Encoding: 7bit

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 ------------WwIskSykX71KN2sh2BqKMU Content-Type: multipart/related; boundary=----------WwIskSykX71KN267VeBiNg ------------WwIskSykX71KN267VeBiNg Content-Type: text/html; charset=utf-8 Content-ID: <op.1279575683379.22436d546d5da4be 10.0.0.88> Content-Transfer-Encoding: Quoted-Printable <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <HTML> <HEAD></HEAD> <BODY style=3D"font-family:'DejaVu Sans Mono'; font-size:12px"><div>On Mon,= 19 Jul 2010 22:42:51 +0200, Philippe Sigaud &lt;philippe.sigaud gmail.com&= gt; wrote:<br><br><blockquote style=3D"margin: 0 0 0.80ex; border-left: #00= 00FF 2px solid; padding-left: 1ex"><div class=3D"gmail_quote">On Mon, Jul 1= 9, 2010 at 22:06, Simen kjaeraas <span dir=3D"ltr">&lt;<a href=3D"mailto:si= men.kjaras gmail.com">simen.kjaras gmail.com</a>&gt;</span> wrote:<br><bloc= kquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-lef= t: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> template hasSetter(alias func) if (isCallable!(func)) {<br><div class=3D"im= "> =C2=A0 =C2=A0enum hasSetter =3D isProperty!(func) &amp;&amp;<br></div> =C2=A0 =C2=A0 =C2=A0 =C2=A0is( typeof( (){ func =3D ReturnType!(func).init= ; } ) );<br> }<br><br></blockquote><div><br>In that case, for the second func, the one y= ou call ReturnType on, how does the compiler knows it must take the ref uin= t one (the getter) and not the void func() one?<br><br><br>Philippe<br> <br><br></div></div> </blockquote><br>Simen is using the fact that the compiler already has to f= igure out if there is an overload that matches the requirements. So it ends= up</div><div>taking the only one that works. Since it seems to ignore the = ref return type property, the property that takes an uint argument must hav= e a</div><div>higher precedence (gets checked if it works first).</div><div=
I wonder if its because Walter probably implemented function overloading b=

eature and not just a implementation side effect.</div><div><br></div><div>= -Rory<br><br></div></BODY></HTML> ------------WwIskSykX71KN267VeBiNg-- ------------WwIskSykX71KN2sh2BqKMU--
Jul 19 2010
prev sibling parent Jonathan M Davis <jmdavisprog gmail.com> writes:
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
Jul 19 2010