Possible way to achieve lazy loading with const objects

Steven Schveighoffer schveiguy at yahoo.com
Thu Sep 29 10:39:41 PDT 2011


On Thu, 29 Sep 2011 13:20:21 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> On 9/29/11 10:15 AM, Steven Schveighoffer wrote:
>> On Thu, 29 Sep 2011 11:45:18 -0400, Andrei Alexandrescu
>> <SeeWebsiteForEmail at erdani.org> wrote:
>>
>>> On 9/29/11 8:38 AM, Steven Schveighoffer wrote:
>>>> On Thu, 29 Sep 2011 11:09:13 -0400, Christophe
>>>> <travert at phare.normalesup.org> wrote:
>>>>
>>>>> "Steven Schveighoffer" , dans le message (digitalmars.D:145738), a
>>>>>>> It is always possible for a non-const version of opEqual to
>>>>>>> forward to
>>>>>>> the const version, so people willing to use a const version do not
>>>>>>> have
>>>>>>> to define a non-const version.
>>>>>>
>>>>>> Again, you still need to define both, this is not a good situation.
>>>>>
>>>>> No, I didn't express myself correctly. The non-const version should
>>>>> forward to the const version *by default*.
>>>>
>>>> Fine, but if you want to define a non-const version that *doesn't*  
>>>> call
>>>> the const version, you have to define both. So even if you *don't*  
>>>> want
>>>> to deal with const, you still do. I should have been clearer, sorry.
>>>>
>>>> Note that the compiler currently calls a global method which accepts  
>>>> two
>>>> non-const Objects. In order for it to support both const and mutable
>>>> versions, it would have to have 4 different functions.
>>>>
>>>> I really don't think all this complexity is worth the benefit. Just
>>>> learn to use const properly, or don't use the operator system to do
>>>> comparisons. Object.opEquals should be const.
>>>
>>> If we make this change we're liable to break all code that defines
>>> opEquals for classes.
>>>
>>> Two versions should be enough: const/const and mutable/mutable, which
>>> by default forwards to const/const. Old code will run unchanged at a
>>> slight efficiency cost due to forwarding. Since it didn't previously
>>> work for const anyway, no harm done.
>>>
>>> New code gets to only override the const/const version.
>>>
>>> Where is this wrong?
>>
>> class MyExistingClass
>> {
>> string name;
>> this(string n) { name = n;}
>> bool opEquals(Object other)
>> {
>> if(auto x = cast(MyExistingClass)other)
>> {
>> return x.name == name;
>> }
>>
>> return false;
>> }
>> }
>>
>> void main()
>> {
>> auto mec = new MyExistingClass("foo".idup);
>> auto mec2 = new MyExistingClass("foo".idup);
>>
>> const mec_const = mec;
>> const mec2_const = mec2;
>>
>> assert(mec == mec2);
>> assert(mec_const == mec2_const); //???
>> }
>>
>> So what does the second assert do?
>
> Should fail during runtime.  Your example does not currently compile so  
> you can't talk about breaking code that currently doesn't work.

Everything compiles except for the second assert.  But just because nobody  
wrote the assert before the change does not mean they will refrain from  
writing it after the change.

The runtime failure makes code that was not quite fully defined (i.e.  
cannot compare two const objects) to badly defined (you can compare them,  
but you get an exception), especially when a const version is *easy* to  
create.  I mean, all you are doing is comparing two immutable strings,  
that should be doable using const.  Now I have to nag the author of  
MyExistingClass to change his opEquals to const.

Compare changing opEquals to const instead of just *adding* a const  
version of opEquals.  With a straight change, the code doesn't compile and  
you put const on opEquals wherever it complains.  Now it's still fully  
defined and runs the same as before.  How is that a bad thing?

-Steve


More information about the Digitalmars-d mailing list