<div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Dec 15, 2012 at 2:50 AM, John McCall <span dir="ltr"><<a href="mailto:rjmccall@apple.com" target="_blank">rjmccall@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">
<div><div><div class="im"><div>On Dec 13, 2012, at 10:01 PM, <a href="mailto:endlessroad1991@gmail.com" target="_blank">endlessroad1991@gmail.com</a> wrote:</div><blockquote type="cite"><div class="gmail_quote">On Thu, Dec 13, 2012 at 4:23 PM, John McCall <span dir="ltr"><<a href="mailto:rjmccall@apple.com" target="_blank">rjmccall@apple.com</a>></span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid"><div><div>On Dec 12, 2012, at 11:45 PM, <a href="mailto:endlessroad1991@gmail.com" target="_blank">endlessroad1991@gmail.com</a> wrote:</div>


<blockquote type="cite"><div>Thanks, that's a very detailed and thorough comment.</div><div> </div><div>MSDN page for __declspec(property): <a href="http://msdn.microsoft.com/en-us/library/yhfk0thd.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/yhfk0thd.aspx</a></div>



<div>we can declare "array-like" property:</div><div>        __declspec(property(get=GetX, put=PutX)) int x[][];</div><div>and access it with indices:</div><div>        var = obj->x[expr1][expr2];</div><div>


it will be translated into:</div>
<div>        var = obj->GetX(expr1, expr2);</div><div> </div><div>And that's what "ParamCount" in "PropertyAttr" is for.</div><div>We don't know how many params until we parse to "int x[][]", so we have to modify the Attr when we get here.</div>


</blockquote><div><br></div></div><div>That documentation says you can declare this as "int x[]" and it permits an arbitrary amount of subscripts, but apparently you can *also* add multiple []s.  It would be good to understand the requirements and limitations of this language feature as implemented in MSVC.  In particular:</div>


<div><br></div><div>1.  Can you directly template these declarations? (template <class T> _declspec(property) T foo;)</div></blockquote><div>No </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">


<div><div>1a.  Are any of the following answers different if T is dependent, and if so, are those likely to be bugs or actually intended?</div><div>1b.  What if you have template <class T> struct A { _declspec(property) T foo; }; and then instantiate the template at T=int[]?</div>


</div></blockquote><div>Yes, this works fine. </div></div></blockquote><div><br></div></div><div>Does it add an expected index argument?</div><div class="im"><div>  template <class T> struct A {</div></div><div>    int *getFoo() { .. }</div>
<div>    int getFoo(int index) { ... }</div><div>    _declspec(property(get=getFoo)) T foo;</div><div>  };</div><div><br></div><div>  int test(A<int[]> &a) {</div><div>    return a.foo[0];</div><div>  }</div><div>
<br></div><div>Does this call getFoo() or getFoo(int)?</div></div></div></blockquote><div>Doesn't compile. Return type of getters must be exactly the same as property type. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">
<div><div><div class="im"><br><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">


<div><div>2.  What's the relationship between []s and the number of indices?</div><div>2a.  Given _declspec(property) int x[], can you in fact use multiple indices with it, like foo.x[2][3]?</div></div></blockquote>

<div>No </div></div></blockquote><div><br></div></div><div>Okay, that actually explicitly contradicts MS's own documentation that you linked above.  Make sure you test this with an unscriptable element type — like int, not int*.</div>
</div></div></blockquote><div>If getter with more/less parameters is defined, you can. Otherwise, you can't. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">
<div><div><div class="im"><br><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">
<div>2b.  If so, what happens if the "element type" is itself subscriptable?</div>

<div>2b.i. _declspec(property) std::vector<int> x[] and foo.x[0][1]?</div></blockquote><div>No </div></div></blockquote><div><br></div></div><div>What do you mean by "no" here?  Are you saying this program was rejected?  What's the error?</div>
</div></div></blockquote><div>Doesn't compile. Error says "GetX() doesn't accept 2 arguments", just like std::vector<int> is not subscriptable. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">
<div><div><div class="im"><br><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">


<div>2b.ii. _declspec(property) int *x[] and foo.x[0][1]?</div></blockquote><div>Yes, this works fine. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">


<div><div>2c.  Do parentheses change these answers at all?</div><div>2c.i. _declspec(property) int* x[] and (foo.x[0])[1]?</div></div></blockquote><div>Yes, this works fine.</div></div></blockquote><div><br></div></div><div>
What about _declspec(property) int x[][] and (foo.x[0])[1]?</div></div></div></blockquote><div>Compiles and runs as expected. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">
<div><div><div class="im"><br><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">


<div>2c.ii. For that matter, given _declspec(property) int x[], is (foo.x)[0] legal at all?</div></blockquote><div>Yes, this works fine.</div></div></blockquote><div><br></div></div>Okay, good.</div><div><div class="im">
<br><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">

<div>2d.  Given _declspec(property) int x[][], can you use fewer subscripts than that?  Can you still use more?</div></blockquote><div>Answer for both questions is NO.</div></div></blockquote><div><br></div></div>Good.</div>
<div><div class="im"><br><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">


<div>3.  Are there restrictions on the element type?</div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">
<div>3a.  Can it be a reference?</div></blockquote><div>Yes </div></div></blockquote><div><br></div></div><div>Okay.  If I have _declspec(property(get=getFoo)) int &foo, can I do</div><div>  x.foo = 7</div><div>with the semantics of x.getFoo() = 7?</div>
</div></div></blockquote><div>No. Seems that it's not that smart. All assignments will be translated into setters. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">
<div><div><div class="im"><br><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">


<div>3b.  Can it be a bounded array type?  (_declspec(property) int x[][10])</div></blockquote><div>No. Seems that whatever you put in the brackets will be ignored, and treated as a param to getter/setter. </div></div></blockquote>
<div><br></div></div>Okay.</div><div><div class="im"><br><blockquote type="cite"><div class="gmail_quote">

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid"><div>3c.  Can it be an unbounded array type if you use, e.g., a typedef?  (typedef int intarr[]; _declspec(property) intarr x;, or intarr x[] for that matter.)  Does this change the behavior of subscripting?</div>


</blockquote><div>Surprisingly, in this situation, the [] in intarr is still interpreted as a param to getter/setter. </div></div></blockquote><div><br></div></div><div>Alright.  My question above about template arguments is designed to figure out whether this is a hack for non-dependent type sugar, or whether it works through anything that extends the type this way.</div>
<div class="im"><div><br></div><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">


<div><div>4.  What exactly does the element type do there?  Is it just for type-checking the property against the accessors?</div><div>4a.  I'd been assuming that the accessors were selected by overload resolution at access time using the name given/inferred in the property attribute.  Is this not true?  Are they selected/filtered by initial type-checking somehow?</div>


</div></blockquote><div>It is true. You can define "T GetV(int, int)" and "T GetV(double, double)". And getter will choose the best match like normal overload functions.</div></div></blockquote><div><br>
</div></div>Okay.</div><div><div class="im"><br><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">


<div><div>4b.  Is access control checked on the accessors from the declaration point of the property or from the use point?</div><div>4c.  Can the accessors be inherited from base classes?  Are normal ambiguity controls enforced?  Can you scope-qualify the accessor names, e.g. get=Base1::getElt?</div>


</div></blockquote><div>Inherit: yes. Ambiguity: yes. Scope-quailify: No, seems that there can only be one identifier after get= or put=. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">


<div>4d.  Are the index types in the accessors limited in some way, or can they be e.g. arbitrary class types?</div></blockquote><div>They can be arbitary types. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">


<div><div><br></div><div>I'm sure we can find more questions. :)</div><div><div><br></div><blockquote type="cite"><div>Considering this situation, is it still possible to do it in your suggested way?</div>
</blockquote><div><br></div></div><div>Sure, that's not really a problem.  One very important thing — something I seem to have unconscionably forgotten put in my initial review — is that this is way, way more than just a property on a FieldDecl;  this really needs to be some new kind of Decl, probably named MSPropertyDecl.  That node would then be a reasonable place to stash things like the expected (minimum?) number of indices and any other important information from type-checking the declaration, e.g. the possibly-filtered lookup results.  You'll probably need to recognize the presence of the attribute in the parser and enter into a completely different Sema entrypoint, kindof like how the 'friend' keyword does.</div>


<span><font color="#888888"><div><br></div><div>John.</div></font></span></div></blockquote></div><div class="gmail_extra"><br> </div><div class="gmail_extra">Based on answers of these questions, let's guess how VC implements property.</div>


<div class="gmail_extra">I think the design principle for them is, reuse existing compiler code as much as possible, and make the solution as simple as possible.</div><div class="gmail_extra">Here are my opinions:</div><div class="gmail_extra">


1. Any [], [10], or [] that comes from typedef, is treated as a param to getter/setter. Hence, they lose their origin semantics meaning.</div></blockquote><div><br></div></div>Right, you need to walk through type sugar.  If template instantiation can't add to the number of arguments, then you'll need to do this at template parse time and then remember it in the MSPropertyDecl.</div>
<div><div class="im"><br><blockquote type="cite"><div class="gmail_extra">2. For accessors, they will be translated into getter/setter.</div>

<div class="gmail_extra">    i. property can be private, as long as getter/setter is public, they work well.</div></blockquote><div><br></div></div>Oh, now that's interesting.  Okay, you'll have to suppress access control on a member lookup that resolves to one of these.</div>
<div><div class="im"><br><blockquote type="cite"><div class="gmail_extra">    ii. getter/setter will be chosen like any normal overloaded functions.</div><div class="gmail_extra">

3. property are treated like normal members. So they can be inherited, and have ambiguity problem when a class has multiple base classes.</div><div class="gmail_extra">The only problem here, is when the element type is subscriptable itself.</div>

<div class="gmail_extra">    i. When it's pointer type, subscripting the property works as expected.</div><div class="gmail_extra">    ii. When it's class type which has overwritten operator[] (no matter vector or self-defined class),  subscripting the property doesn't compile.</div>

<div class="gmail_extra">I can't guess why this happens.<br clear="all"></div></blockquote><div><br></div></div>If int x[] can, in fact, take more than one subscript (as documented), then I would guess that the rule is that all possible subscripts are consumed by the property *unless* the element type is "obviously subscriptable", which is probably defined as "a pointer type" and doesn't recognize classes with operator[]s.  Interesting corner cases here would be</div>
<div>  int *&x[]; // does it realize that this result type is still "obviously subscriptable"?</div><div>  int *x[]; // if I do a.x[0][1][2], does it steal both [0] and [1] for the subscript, or does it steal just [0] and then try to subscript int* twice (which will fail, of course)?</div>
</div></blockquote><div>Here's two good samples, I think:</div><div> </div><div>#include <iostream></div><div>class C<br>{<br>public:<br> __declspec(property(get=GetA, put=SetA)) int **A[];<br> int** GetA(int i) { std::cout << "Get\n"; return &v; }<br>
 void SetA(int i, int **value) { std::cout << "Set\n";}<br> int *v;<br>};</div><div>int main()<br>{<br> C c;<br> c.A[123][0][0] = 2; // GetA()<br> // c.A[123][0] = 2; // doesn't compile! "Cannot convert int to int*"<br>
 c.A[1] = 0; // SetA()<br>}</div><div> </div><div> </div><div>#include <iostream></div><div>class C<br>{<br>public:<br> __declspec(property(get=GetA, put=SetA)) int *A[];<br> int* GetA(int i) { std::cout << "Get 1\n"; return v; }<br>
 int* GetA(int i, int j) { std::cout << "Get 2\n"; return v; }<br> void SetA(int i, int *value) { std::cout << "Set 1\n"; }<br> void SetA(int i, int j, int *value) { std::cout << "Set 2\n"; }<br>
 int *v;<br>};</div><div>int main()<br>{<br> C c;<br> c.A[123][0] = 2; // Get 1<br> c.A[1] = 0; // Set 1<br>}</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">
<div><div><br></div><div>If int x[] really cannot take more than one subscript, then I have no idea why subscripting vector<int> x[] twice wouldn't compile;  probably just a compiler bug.</div><span><font color="#888888"><div>
<br></div><div>John.</div></font></span></div></blockquote></div><br>And, can you summarize how we should implement property, based on these results?<br clear="all"><br>-- <br>Best Regards, Tong Shen (沈彤)<br>
</div>