On Thu, 29 Sep 2011 11:45:18 -0400, Andrei Alexandrescu <seewebsiteforem...@erdani.org> wrote:

On 9/29/11 8:38 AM, Steven Schveighoffer wrote:
On Thu, 29 Sep 2011 11:09:13 -0400, Christophe
<trav...@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? With the current compiler, it should fail to compile (not sure if it does, I know there was a bug where it used to pass).

The current Object has a default equality comparison that checks for identity. Is that what the default const version would do? In that case, the first assert passes, whereas the second assert fails.

If we make the default const opEquals throw, then this breaks existing code for classes which *don't* implement opEquals.

Any way you slice it, code is going to break. I'd rather it break in the compile phase then silently misbehave later.

-Steve

Reply via email to