On Sunday, 7 April 2024 at 09:59:56 UTC, Jonathan M Davis wrote:
> No, we really don't want to force @safe on opEquals, because that means that you can't write one that's @system, meaning that you're potentially forced to use @trusted on code that really shouldn't be treated as @safe.
Well, I already ended up putting @trusted
in a function I didn't want to put it in because opEquals
was @system
. Point taken though.
> class C
{
bool opEquals(C rhs) @safe
{
...
}
override bool opEquals(Object rhs) @safe
{
...
}
}
then the first overload will be called when comparing class references of type C - or class references derived from C, whereas if you're comparing class references of type Object (or class references which aren't C or derived from C), then they'll be compared as Object, and the base class opEquals will be called, resulting in your second overload being called thanks to polymorphism, but because the base class version is @system, == will still be treated as @system in that case. E.G.
Oh! Is this how the opEquals
function used can be made to depend on the reference type, rather than the type of the object contained in the reference?
> > Anyway, I discovered that ==
can be replaced with is
, and it seems to do the same thing while working within a @safe
function.
The is operator and == are not the same. When you use is on class references, it's true if and only if the two references point to the same object. It's basically doing a pointer comparison. In contrast, == calls the free function, opEquals, which will call opEquals on the class references to compare them if they're not null and they're not pointing to the same object.
Right. I was just saying that is
will in most cases give the same results as the default opEquals
function. The existence of is
means I no longer think opEquals
should be @safe
by default. The only place where they would differ is when the first reference is null, right?
Ultimately, not knowing to use is
is what lead me to making this topic.
Actually, I just looked in the base object definition, and I found this:
bool opEquals(Object o)
{
return this is o;
}
It looks like it really would be the same whenever the first reference is a valid object. I figure it would segfault if the first reference is null, while is
would simply return false
.
> You already need to do an override to get opEquals unless you want it to just compare the references, which is borderline useless. All that opEquals on Object does is compare the addresses of the references with the is operator, and that's almost never what you want when doing an equality check.
Well, it's exactly what I wanted, but I'm new to the language, and hadn't yet been taught to use is
in such cases. For the function I was writing, see Weapon.getOptions
or look for if (user.currentWeapon == this)
in this module.
Now knowing about the proper uses of ==
and is
, I think the only worthy idea I have for a new addition to the language is a new function in std.algorithm.searching
; a @safe bool
function called contains
. It would return whether the first argument (an array of the second argument's type) contains the second argument. It would be equivalent to canFind
for some argument types, but for objects it would do an is
comparison.
Perhaps I can try to implement this myself. Given my inexperience, chances are someone else would make some edits to it before getting merged into Phobos.