No we should not support enum types derived from strings
deadalnix
deadalnix at gmail.com
Wed May 12 01:46:25 UTC 2021
On Tuesday, 11 May 2021 at 21:36:46 UTC, Andrei Alexandrescu
wrote:
> Values are monomorphic. Years ago I found a bug in a large C++
> system that went like this:
>
> class Widget : BaseWidget {
> ...
> Widget* clone() {
> assert(typeid(this) == typeid(Widget*));
> return new Widget(*this);
> }
> };
>
> The assert was a _monomorphism test_, i.e. it made sure that
> the current object is actually a Widget and not something
> derived from it, who forgot to override clone() once again.
>
> The problem was the code was doing exactly what it shouldn't
> have, yet the assert was puzzlingly passing. Since everyone
> here is great at teaching basic type theory, it's an obvious
> problem - the fix is:
>
> assert(typeid(*this) == typeid(Widget));
>
> Then the assertion started failing as expected. Following that,
> I've used that example for years in teaching and to invariably
> there are eyes going wide when they hear that C++ pointers are
> monomorphic, it's the pointed-to values that are polymorphic,
> and that's an essential distinction. (In D, just like in Java,
> classes take care of that indirection automatically, which can
> get some confused.)
While this is indeed very interesting, this is missing the larger
point.
This whole model in C++ is unsound. It's easy to show. In you
above example, the this pointer, typed as Widget*, points to an
instance of a subclass of Widget. If you were to assign a Widget
to that pointer (which you can do, this is a pointer to a mutable
widget), then any references to that widget using a subtype of
Widget is now invalid.
There is no such thing as a monomorphic pointer to a polymorphic
type in any sound type system. That cannot be made to work. It is
unsound. This is why in Java or C#, the type represent both the
pointer and the pointed data, as a package, being half a value,
half a reference type in the process. This is unavoidable, you
can't unbundle it or everything breaks down.
So why is there an indirection in there? Simply because you
cannot know the layout of the object at compile time when you are
doing runtime polymorphism. But even then, you could decide to
make it behave as a value type with eager deep copy or copy on
write and that would work too, and it would still be polymorphic.
D is correct to use Java and C# 's model. C++'s is unsound.
But we get back to square one: this has nothing to do with the
indirection. In fact, in the Java/C# model, class types are value
type, which hold a reference to a payload. And the whole typing
and subtyping business happen on these value types.
More information about the Digitalmars-d
mailing list