tail const

Michel Fortin michel.fortin at michelf.com
Sat Dec 4 04:22:41 PST 2010


On 2010-12-04 07:13:30 -0500, Michel Fortin <michel.fortin at michelf.com> said:

> On 2010-12-04 02:48:26 -0500, Dmitry Olshansky <dmitry.olsh at gmail.com> said:
> 
>> On 04.12.2010 6:23, Andrei Alexandrescu wrote:
>>> On 12/3/10 7:40 PM, Michel Fortin wrote:
>>>> I have an idea that would fix those: make a template struct/class
>>>> instance implicitly convertible to another instance of that same
>>>> template if all members share the same memory layout and each member is
>>>> implicitly convertible to the same member of the other template.
>>> 
>>> I'm afraid that can't work.
>>> 
>>> struct A(T) {
>>>     T obj;
>>>     void fun() { obj->method(); }
>>> }
>>> 
>> 
>> Looks discouraging at first, but perfectly valid given that the example 
>> works only when A!Object compiles, i.e. Object have method 'method', 
>> and then:
>> 
>>> auto a = new A!Widget;
>>> a.obj = new Widget;
>>> A!Object b = *a; // works because Widget converts to Object
>> // A!Object* b = a; // should not compile, and would be a problem if A 
>> is a class
>> //now we have another struct b with reference to a's widget
>>> b.obj = new Object; //no problem, a stays intact
>>> b.fun(); // since A!Object already compiles, it's perfectly valid
>> 
>> In fact, it looks like Michel's rule is very promising, just replace 
>> "struct/class" part with "struct" in definition.
> 
> Yes, indeed. I was a little over-enthusiastic when saying it'd work for 
> classes too; the vtable pointer would be a problem for that. But it 
> seems it can work well for structs.
> 
> You're right, "A!Object b = a" should compile fine while "A!Object* b = 
> &a;" should not, because it'd allow you to assign any Object to the 
> Widget field. That said, you can still allow this convertion: 
> "A!(const(Object))* b = &a;". That's because the obj member becomes 
> const and you can no longer assign anything to it.

That wasn't very well put. Here I was looking only at the obj field. As 
defined above it wouldn't compile because "fun() { obj.method() }" 
won't compile for Object and the template won't instanciate. Please 
ignore "fun()" when reading all this.

> So, to refine the rules I'd say a templated struct can be converted to 
> a lvalue of another instance of the same templated struct with the same 
> memory layout if all members can be converted to a lvalue of their type 
> in the second struct. If one field can only be converted as a rvalue, 
> the result is a rvalue struct. We should also make it so Widget can 
> convert to const(Object) as an lvalue; that doesn't work currently.


-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



More information about the Digitalmars-d mailing list