Bug 8545 – defined opCast disables cast(void*)this in classes
Status
RESOLVED
Resolution
INVALID
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-08-12T20:33:46Z
Last change time
2023-01-02T08:31:28Z
Assigned to
No Owner
Creator
Andrej Mitrovic
Comments
Comment #0 by andrej.mitrovich — 2012-08-12T20:33:46Z
class Foo
{
T opCast(T : int)() { return 1; }
void* test() { return cast(void*)this; }
}
void main() { }
This is problematic, cast(void*)this is the trick used to get the address of 'this' object. &this is the address of the reference and can't be used for the same purpose. So defining opCast for any type ends up disabling 'cast(void*)this'.
I honestly think we should have a druntime function or some kind of compiler intrinsic to get the equivalent of 'cast(void*)this'. That cast itself looks too hacky to begin with.
Comment #1 by andrej.mitrovich — 2012-08-12T20:35:06Z
Oh and the error message, not that it matters:
Error: template instance opCast!(void*) opCast!(void*) does not match template declaration opCast(T : int)
Comment #2 by bugzilla — 2012-08-12T21:50:50Z
I don't think this is major, because you can use a union:
{
static union U { Object o; void* p; }
U u;
u.o = this;
return u.p;
}
In fact, because a union can be used for reinterpret casting, I don't think any new syntax or semantics are needed.
Comment #3 by andrej.mitrovich — 2012-08-13T07:57:58Z
(In reply to comment #2)
> I don't think this is major, because you can use a union:
>
> {
> static union U { Object o; void* p; }
> U u;
> u.o = this;
> return u.p;
> }
>
> In fact, because a union can be used for reinterpret casting, I don't think any
> new syntax or semantics are needed.
I'm speaking in terms of wrapping C++ libraries (A C++ wrapper class has an inner d_object pointer which it uses to invoke D virtual methods). You're asking me to introduce overhead for every time a new class object is instantiated.
Comment #4 by art.08.09 — 2012-08-14T03:21:53Z
(In reply to comment #3)
> (In reply to comment #2)
> > I don't think this is major, because you can use a union:
> >
> > {
> > static union U { Object o; void* p; }
> > U u;
> > u.o = this;
> > return u.p;
> > }
> >
> > In fact, because a union can be used for reinterpret casting, I don't think any
> > new syntax or semantics are needed.
>
> I'm speaking in terms of wrapping C++ libraries (A C++ wrapper class has an
> inner d_object pointer which it uses to invoke D virtual methods). You're
> asking me to introduce overhead for every time a new class object is
> instantiated.
The compiler /should/ handle it w/o any additional runtime overhead. You could also use
void* test() { return *cast(void**)&this; }
Which approach will be more efficient probably depends on compiler implementation; ideally both versions should be free.
Comment #5 by andrej.mitrovich — 2012-08-14T08:18:35Z
> You could also use
>
> void* test() { return *cast(void**)&this; }
>
Thanks! It does seem to create the exact same assembly even with no optimizations.
Comment #6 by alphaglosined — 2023-01-01T18:18:13Z
I'm reopening this bug report for two reasons:
1. Hipreme ran into this when creating a class manually which had opCast defined.
2. With the current work replacing _d_newclass with a template, new will no longer work with a class that isn't ultra-specific with its opCast. In practice this will be a breaking change, so it's time to fix this bug to prevent code breakage.
Comment #7 by alphaglosined — 2023-01-02T08:31:28Z
Closing again, because I did make a mistake.
The new class hook won't need this, and destroy already works. So even if this doesn't make sense why it wasn't fixed, I'll put it back to original state.