No struct extending?

Steve Horne stephenwantshornenospam100 at aol.com
Fri Sep 8 05:42:37 PDT 2006


In C++, 'struct' is (almost) a synonym for 'class'. More a declaration
of intent than a different thing. One useful side-effect of this is
that you can declare structs as extensions of other structs. This can
be useful even for plain-old-data. e.g. data structures with several
node types, but some shared fields. Inheritance doesn't always imply
virtual tables and stuff.

Of course you can handle this using...

  struct s_Branch
  {
    s_Common m_Common;

    ... (branch specific stuff)
  }

But all that 'pointer.m_Common.actual_member' is a pain.

Adding a union...

  union u_Variant
  {
    s_Common m_Common;
    s_Branch m_Branch;
    s_Leaf   m_Leaf;
  }

just means you have to specify 'm_Branch' or 'm_Leaf' for the
non-shared fields too.

Anonymous structs and unions can save on these extra dots and
identifiers, but they do a different job. They can't give you a family
of structs. Only a single struct/union combo - a variant record.

Plus, one thing I have in mind is templates that build up in layers
(mix-in layers pattern), and there will be an arbitrary number of
extensions applied. For example, if you want ordered keys, you apply
the 'gimme-keys' template as a mixin layer, and it extends whatever
structures, classes and methods it needs to.

This can still be handled - you just compose an access class in
parallel along with the structs. But it's a hassle.

Now, truth told, this mix-in layers bit isn't important. 'static if'
probably means I'm better off specifying things using mix-in layers
(setting up flags and aliases), but putting most of the final code in
one big template. It will be a lot more readable and maintainable that
way. The mix-in layers pattern is then mostly a way of avoiding having
too many parameters for one template.

I could use a D mixin to define the common fields, of course. And
whatever approach I take, there's pointer casting based on the
run-time type so that's not a big deal, though the C++ approach is
nice in that casting to the 'base struct' is implicit.

What bothers me is the chance of this happening...

  struct c_Common
  {
    mixin(common fields)
  }

  struct c_Leaf
  {
    int m_Misplaced_Field;  //  whoops!
    mixin(common fields)
  }

Or, for that matter, the same just using nested structs.

  struct s_Branch
  {
    int      m_Misplaced_Field;  //  whoops!
    s_Common m_Common;
  }

That is, there is no rule forcing the shared part into matched
locations in all structures, so when you do the union/pointer
casts/whatever you can end up looking at the wrong memory.

So - am I being paranoid?

It's a small thing, especially given the amount of work that D has
already saved me. And I'm not even convinced it's real. The node
layouts above, for instance, will all be part of the same module and
maintained together anyway. The odds of a misplaced field like that
should be next to zero, and the same probably applies in any family
tree of related structs.

I just thought I'd raise it and see what others think.

-- 
Remove 'wants' and 'nospam' from e-mail.



More information about the Digitalmars-d mailing list