class A
{
}
class B
{
A a;
alias a this;
}
class C : B
{
}
void main()
{
A a = new C; // error
}
Error: cannot implicitly convert expression (new C) of type test.C to test.A
Since C is a subtype of B (via inheritance) and B is a subtype of A (via "alias this"), C should be implicitly convertible to A.
Comment #1 by bugzilla — 2010-12-27T13:33:28Z
Yes, I see the problem. Never thought of that.
Comment #2 by samukha — 2012-11-28T07:16:16Z
This one is blocking a design for QtD (and potentially other C++ projects using single inheritance with interfaces) that should allow at the cost of relatively small constant overhead to avoid:
1) unnecessary and undesirable allocations or lookups of wrapper objects for object pointers returned by the C++ code.
2) bloating the library with virtual call dispatchers for objects that are never inherited in D code.
Very roughly:
// Instead of classes, fat pointers are generated for C++ classes:
struct QObject
{
bool isDWrapper;
void* pointerToCppObject;
// a virtual
void foo() {
if (isDWrapper)
// dispatch to the D override
else
// make static call to C++
}
enum dispatchers = q{
void foo() {
// dispatch to C++
}
};
}
// Library
class Inherit(T)
{
T ref_;
alias ref_ this;
mixin(T.dispatchers);
this() { isDWrapper = true; }
}
// User
class MyObject : Inherit!QObject
{
override void foo()
{
...
super.foo();
...
}
}
// Some function taking a QObject
void bar(QObject obj)
{
obj.foo();
}
void main()
{
// Here is the problem: MyObject is not a subtype of QObject
bar(new MyObject);
}
The Inherit template subtypes the struct and provides the implementation of the overrides dispatching calls to the C++ side. If the user does not inherit from a Qt class (which will be true for most classes), the overrides are never compiled into the library. When receiving an object from the C++ side, we do not need to allocated a wrapper objects, just initialize the fat pointer with the relevant information.
I am not sure whether the craziness of the above is going to make it into the project but a prototype I've created does work.
Now that we can link to 64-bit C++ libraries directly on windows, we *maybe* could try to use (and improve) extern(C++) interfaces in order to avoid the complications. I am still not sure what to do with 32-bit Windows and would rather give a try to the design described.
Comment #3 by verylonglogin.reg — 2013-11-09T04:38:39Z
*** Issue 5973 has been marked as a duplicate of this issue. ***
Comment #4 by verylonglogin.reg — 2013-11-09T04:41:24Z
From Kenji Hara's Issue 5973 description:
Following should compile, but not.
(In comment, -> is superclass lookup, => is alias this lookup)
---
class A { int a = 1; }
class B { int b = 2; }
class C: A
{
B obj;
alias obj this;
this() { obj = new B(); }
}
class X: C { }
void main()
{
auto c = new C();
assert(c.a == 1); // lookup C -> A, OK
assert(c.b == 2); // lookup C => B, OK
auto x = new X();
assert(x.a == 1); // lookup X -> C -> A, OK
assert(x.b == 2); // lookup X -> C => B, NG (Line 17)
}
---
test.d(17): Error: no property 'b' for type 'test.X'
---
---
Comment #5 by simen.kjaras — 2018-06-28T06:34:13Z
*** Issue 19032 has been marked as a duplicate of this issue. ***
Comment #6 by razvan.nitu1305 — 2018-10-09T17:29:22Z
This is much more of a perplexing problem than it first appears. What order are things looked up in? Is the alias-this looked up first, or the base classes? Or are they looked up as the base classes are looked up? What happens if two different symbols are found via different orderings of when lookups are done? What happens if the same symbol is found via different lookup paths?
This is the old multiple inheritance problem from C++, one I had wished to avoid in D.
Max Samukha's comment is a way to inherit class types from struct types, one use I had not anticipated, and makes me want to step back and question is this really where we want to go with this?
At least with the current implementation, things are a bit straightforward. The base classes are looked at. If not found there, the alias-this is looked at, and that's it.
Comment #8 by alexanderheistermann — 2018-12-02T18:41:23Z
This shouldn't be closed. Either the implementation needs to be modified to allow it or the spec needs to specify that alias this in a super class is not considered in its subclasses.
Comment #11 by razvan.nitu1305 — 2022-09-08T09:11:15Z
*** Issue 8663 has been marked as a duplicate of this issue. ***
Comment #12 by robert.schadek — 2024-12-13T17:54:38Z