digitalmars.D.learn - Prevent self-comparison without taking the address
- Dom DiSc (15/15) Jul 25 I have copied some source from C++, where the following pattern
- IchorDev (9/11) Jul 25 When a parameter is `ref` it is treated as a value type (i.e. it
- IchorDev (4/8) Jul 25 Also just so you know, placing `@safe:` there will not affect the
- Dennis (3/6) Jul 25 That's true for the other function attributes, but `@safe:`
- IchorDev (3/5) Jul 25 The spec doesn’t mention this at all! Is this the case for any
- Dom DiSc (5/10) Jul 25 As he said: no. It's only true for @safe:
- IchorDev (17/21) Jul 25 No they did not, they specifically said that my assertion holds
- Nick Treleaven (3/6) Jul 25 Just to mention that with -dip1000, taking the address of
- Dom DiSc (6/12) Jul 26 Thanks for all the good answers.
- Jonathan M Davis (23/38) Jul 25 If you want to do that, that's basically what you would need to do. Howe...
I have copied some source from C++, where the following pattern is common (operator== already renamed): ```d safe: struct S { bool opEquals(const ref S x) const { if(&x==&this) return true; ... } } ``` Can I replace this pattern with ```(x is this)``` or are there some special cases where this doen't work?
Jul 25
On Thursday, 25 July 2024 at 10:50:04 UTC, Dom DiSc wrote:Can I replace this pattern with ```(x is this)``` or are there some special cases where this doen't work?When a parameter is `ref` it is treated as a value type (i.e. it has value semantics), even though it is a reference; therefore an identity expression of `x is this` will check whether the bits in `x` and `this` are identical: https://dlang.org/spec/expression.html#identity_expressions Using the reference operator (`&`) on something that is `ref` returns its pointer form, which is what you want to compare. TL;DR: No, `is` will compare the struct data not the pointers.
Jul 25
On Thursday, 25 July 2024 at 10:50:04 UTC, Dom DiSc wrote:```d safe: struct S{ ```Also just so you know, placing ` safe:` there will not affect the contents of `S`. It has to be inside the struct declaration to affect its contents.
Jul 25
On Thursday, 25 July 2024 at 11:46:29 UTC, IchorDev wrote:Also just so you know, placing ` safe:` there will not affect the contents of `S`. It has to be inside the struct declaration to affect its contents.That's true for the other function attributes, but ` safe:` actually does penetrate scopes
Jul 25
On Thursday, 25 July 2024 at 13:01:53 UTC, Dennis wrote:That's true for the other function attributes, but ` safe:` actually does penetrate scopesThe spec doesn’t mention this at all! Is this the case for any other `AttributeSpecifier` declarations?
Jul 25
On Thursday, 25 July 2024 at 13:20:59 UTC, IchorDev wrote:On Thursday, 25 July 2024 at 13:01:53 UTC, Dennis wrote:As he said: no. It's only true for safe: But that doesn't answer my question. You said it is not the same. But then: is there another way to translate the C++ pattern in a safe way?That's true for the other function attributes, but ` safe:` actually does penetrate scopesThe spec doesn’t mention this at all! Is this the case for any other `AttributeSpecifier` declarations?
Jul 25
On Thursday, 25 July 2024 at 14:05:50 UTC, Dom DiSc wrote:As he said: no. It's only true for safe:No they did not, they specifically said that my assertion holds true for all other [function attributes](https://dlang.org/spec/attribute.html#function-attributes). This does not tell me anything about other attributes like `align`, `deprecated`, ` __future`, linkage attributes, visibility attributes, mutability attributes, shared storage attributes, ` system` variables, or UDAs.But that doesn't answer my question.Your question was ‘Can I replace this pattern with `(x is this)`’. The answer is no.You said it is not the same. But then: is there another way to translate the C++ pattern in a safe way?This is the first time you have mentioned this intention with words. I’m not a mind reader. I think your function most likely has a safe interface, so it can be marked as ` trusted` as-per [the spec](https://dlang.org/spec/function.html#safe-interfaces). Let’s go through the checklist: - undefined behaviour? Nothing undefined about comparing two numbers. - creates unsafe values accessible by safe code? No it only returns a Boolean. - unsafe aliasing accessible by safe code? No aliasing whatsoever.
Jul 25
On Thursday, 25 July 2024 at 15:06:35 UTC, IchorDev wrote:I think your function most likely has a safe interface, so it can be marked as ` trusted` as-per [the spec](https://dlang.org/spec/function.html#safe-interfaces).Just to mention that with -dip1000, taking the address of variables is allowed, so the function would be safe.
Jul 25
On Thursday, 25 July 2024 at 15:40:29 UTC, Nick Treleaven wrote:On Thursday, 25 July 2024 at 15:06:35 UTC, IchorDev wrote:Thanks for all the good answers. So the solution for me is -dip1000. Marking something trusted that the compiler should be able to check to be safe is not so good, as it increases the review effort significantly and unneccessarily.I think your function most likely has a safe interface, so it can be marked as ` trusted` as-per [the spec](https://dlang.org/spec/function.html#safe-interfaces).Just to mention that with -dip1000, taking the address of variables is allowed, so the function would be safe.
Jul 26
On Thursday, July 25, 2024 4:50:04 AM MDT Dom DiSc via Digitalmars-d-learn wrote:I have copied some source from C++, where the following pattern is common (operator== already renamed): ```d safe: struct S { bool opEquals(const ref S x) const { if(&x==&this) return true; ... } } ``` Can I replace this pattern with ```(x is this)``` or are there some special cases where this doen't work?If you want to do that, that's basically what you would need to do. However, I've never seen anyone do that with structs in D. They're usually put on the stack and passed around by value. They are of course sometimes passed by reference, but that's usually going to be to a variable on the stack, making comparing addresses kind of pointless, since you'd usually need to be doing something like x == x to end up comparing the same object against itself. Pretty much the only time that something like this might make sense is when you're dealing with pointers to structs, which of course is done sometimes, but it's much less common than it would be in C++, since D separates classes and structs. And classes already do that check with ==, since it's lowered to a free function, opEquals, before calling the class' opEquals, and it does stuff like compare the address of the class reference and compare against null. Either way, the fact that the this member for structs is a reference rather than a pointer means that if you want to compare addresses, you'll need to take the addresses - which won't be safe without DIP 1000, because taking the address of a local variable is not safe without the tracking that DIP 1000 adds via scope (since without the extra checks, you could easily take that address and pass it around, letting it escape the lifetime of the reference). - Jonathan M Davis
Jul 25