Walter's second axiom
Bill Baxter
dnewsgroup at billbaxter.com
Sat Dec 8 05:05:16 PST 2007
Janice Caron wrote:
> As discussed elsewhere, Walter's second axiom states: for any type T,
> it should be possible to construct a struct S which behaves exactly
> like a T, by wrapping T inside a struct and adding extra member
> functions, like so:
>
> struct S
> {
> T t;
> /* functions */
> }
>
> However, there is at least one violation of the axiom: inheritance. As follows:
>
> class C {}
> struct S { C c; }
>
> I can do
>
> class D : C {}
>
> but I can't do
>
> class D : S {}
>
> thus, S cannot be made to behave exactly like C, and so the axiom does not hold.
There are various other ones that have to do with return of lvalues (or
lack thereof).
For instance, if T is int[], you can do t[0]++ but you can't do that for
a struct that wraps an int[].
Also the thing about default initializers for struct wrappers. Perhaps
that's just a bug, though. Walter hasn't commented whether he intends
to make that work or not. The example is wrap a numeric type and give
it all the bells it needs to initialize it with a regular number, like
MyInt x = 5. Now try to use it as a paramter with default:
void func(MyInt x = 5) // error
But I think axiom 2 is great and I'd love to see a solution for all of
the holes that prevent making a wrapper behave exactly like another type.
> The solution is to provide structs with some mechanism that allows
> classes to inherit from them - such as, for example, opInherit()
>
> struct S
> {
> C c;
> C opInherit() { return c; }
> }
>
> A class could then inherit from either a class, or from a struct which
> supplies opInherit(). opInherit() itself must, of course, return
> either a class, or a struct which supplies opInherit().
>
> This is not a feature request as such. I'm just mentioning - from a
> purely theoretical standpoint - a violation of Walter's second axiom,
> and a possible remedy.
>
> (And just to stir things up further, I think that interfaces violate
> the second axiom also) :-)
I think maybe that's going to far. There are some places where you
cannot and should not have a wrapper act like the type it wraps. The
main one that comes to mind is an 'is' check. is(MyWrapper ==
RealClass). Obviously that should fail. But it stands to reason that
there are perhaps some other operations that are so closely tied to the
actual type that they shouldn't be expected to work with a wrapper. I
think inheritance is maybe one of those.
--bb
More information about the Digitalmars-d
mailing list