DIP66 - Multiple alias this
Mike
slavo5150 at yahoo.com
Wed Sep 30 01:36:59 UTC 2020
On Monday, 28 September 2020 at 19:55:10 UTC, Andrei Alexandrescu
wrote:
> I'd love to get a better idea about this, e.g. a few clear
> examples of bad uses and other few good examples where it's a
> win. My intuition vaguely revolves around "aliasing to an
> rvalue is bad and lvalue is good" but I year for clarity.
What's good about `alias this`
------------------------------
`alias this` is used for 2 primary purposes:
1. Forwarding a member's interface to its containing object's
interface
2. Implicit casting and subtyping which are fundamentally
different but with similar use cases
```
struct A { int x; }
struct B
{
A a;
alias a this;
int y;
}
void PassA(A a) {}
void main()
{
B b;
int i = b.x; // A.x was forwarded through B
int j = b.y;
PassA(b); // B was implicitly cast to A
}
```
`alias this` is actually useless for classes, because the same
thing can be achieved with inheritance:
```
class A { int x; }
class B : A
{
int y;
}
void PassA(A a) {}
void main()
{
auto b = new B();
int i = b.x; // A.x was forwarded through B
int j = b.y;
PassA(b); // B was implicitly cast to A
}
```
What's bad about `alias this`
-----------------------------
Walter addressed the problem with `alias this` here:
> If a class hierarchy has alias this, when does the compiler go
> looking down the alias this, and when does it go looking at the
> base class and interfaces? (Of course the base class can have
> an alias this, and an alias this can have a base class.) You
> have essentially *two* multiple inheritance systems in play at
> the same time, each obeying different rules.
> Couple that with the current arbitrary random rules about how
> alias this behaves for classes, and any coherent MI alias this
> scheme would randomly break existing code.
In other words, its too complex, and adding multiple `alias this`
would only compound that complexity.
My 2 cents
----------
`alias this` is useless for classes unless users want to abuse it
to create "dual" inheritance by both inheriting from another
class, and `alias this` a member simultaneously. Just use
inheritance. If you need multiple inheritance, inherit from
multiple interfaces and use D's excellent metaprogramming
facilities to auto-implement each interface, or auto-forward
members that implement the interfaces.
```
interface A { @property int x(); }
mixin template Aimp()
{
@property int x() { return 0; }
}
interface B { @property int y(); }
mixin template Bimp()
{
@property int y() { return 0; }
}
class C : A, B
{
mixin Aimp;
mixin Bimp;
}
void PassA(A a) {}
void PassB(B b) {}
void main()
{
auto c = new C();
int i = c.x; // A's implementation in C
int j = c.y; // B's implementation in C
PassA(c); // C implicitly cast to A
PassB(c); // C implicitly cast to B
}
```
Where `alias this` has no alternative for structs because structs
cannot inherit and cannot implement interfaces. D has sufficient
metaprogramming facilities to auto-forward members, but the
missing piece is implicit casting.
```
mixin template Aimp()
{
int x;
}
mixin template Bimp()
{
int y;
}
struct C
{
mixin Aimp;
mixin Bimp;
}
void PassA(A a) {} // Error: What do we put here when we want a
type that implements `A`. There is no such type?
void PassB(B b) {} // Error: What do we put here when we want a
type that implements `B`, There is no such type?
void main()
{
auto c = new C();
int i = c.x; // A's implementation in C
int j = c.y; // B's implementation in C
PassA(c); // Error: C cannot implicitly cast to A
PassB(c); // Error: C canot implicitly cast to B
}
```
So, here are a couple of proposals off the top of my head. I
imagine someone more talented than I can think of a few more:
1. Deprecate `alias this` for classes, and implement multiple
`alias this` for structs. That will give users the composition
feature they need, and in addition, because structs cannot
inherit, it removes the complexity Walter spoke of.
2. Add `opImplicit`, implicit copy constructors, or something of
that ilk. Then users only need to forward members using D's
metaprogramming facilities. Both uses of `alias this` are
covered, but no `alias this` is required. `alias this` can then
be deprecated entirely.
3. Add struct inheritance like C++.
More information about the Digitalmars-d
mailing list