Re: Pointer to "base" type - what does the Standard say about this?



A follow up on how i got to a safe solution...

On Nov 6, 7:07 am, Stephan Beal <sgb...@xxxxxxxxxxxxxx> wrote:
On Nov 5, 11:07 pm, Eric Sosman <Eric.Sos...@xxxxxxx> wrote:
One clean way to handle this is to pack all the allied types
into a union, but this requires that you know all those types up

i've ruled out the union idea because concrete impls can be provided
by client code, and i obviously can't link those in to my lib.

front, which can be irksome. Another clean way to handle it is to
use a `base_api*' and point it at the `api' element of whichever
structs you're dealing with. Since the `api' is the first element
in each struct, it is always safe to convert the struct pointer to
a `base_api*' and back.

Here's what i've ended up doing, which offers both an approach with
the safety guaranty approach and the extension-which-might-work-but-is-
technically-unsafe approach:

typedef struct base_api {
void (*member1)( struct foo const * self );
int (*member1)( struct foo const * self, int arg1 );
...
void const * implData;
} base_api;

Now my Base type looks like:

typedef struct base {
base_api const * api;
};

(This extra level of indirection isn't really necessary any longer,
and i may get rid of it.)

For my particular cases, all of my implementations can (and in fact
should) be initialized with constant, immutable data (it may be
instance-specific but should be immutable). With this approach i no
longer need concrete "subclasses" - i only need concrete
implementations of base, which allows me to completely avoid the
((base*)mySubT) cast. The impl functions can require that the api-
implData object be set to some implementation-specific value, which
the impls can then cast to their heart's content.

What's all this for?

As part of c11n (http://s11n.net/c11n/) i need abstract interfaces for
3 particular object types. The interfaces are used by the rest of the
API and only care that impls follow the rules defined in the API docs
for the base class API. For example, i have an interface called
c11n_marshaller, which is a marshaller type for de/serializing objects
of a specific type (we need one implementation/instance per
serializable type). Some common cases (e.g. well-known PODs) can be
combined into a single implementation of the base_api functions,
differing only in the metadata they need for the marshalling
conversion. To do this we point the api->implData to some instance-
specific static struct containing that metadata which differs from POD
type to POD type (e.g. a printf/scanf specifier). For the c11n_stream
interface, the (void * implData) (non-const) member will hold info for
the underlying native stream object (e.g. FILE handle or in-memory
buffer).

Anyway...

Thanks a thousand times to all of you for your feedback - it's helped
me move away from a potentially horrible design mistake!
.



Relevant Pages

  • Exposing internal members of an assembly
    ... I am trying to have a set of base classes and interfaces of an ... the abstract classes and interfaces. ... The problem is that some parts of the API are "internal" in the sense ... the implementations will not be able to access ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Exposing internal members of an assembly
    ... the abstract classes and interfaces. ... The problem is that some parts of the API are "internal" in the sense ... the implementations will not be able to access ... So you want the derived classes to have access to the members in the ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Declaring a Constructor in an Interface?
    ... All these objects have completely different implementations ... i use interfaces rather than abstract classes for this. ... Abstract base classes don't have that feature - you> can only have a single base class. ... For example, if you derive from XmlReader,> not only does that mean that your class provides the XmlReader API, it also> means you get a certain amount of help: you are not obliged to implement the> entire thing from scratch. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Declaring a Constructor in an Interface?
    ... classes and interfaces is so small that you can ignore it for the vast ... can only have a single base class. ... not only does that mean that your class provides the XmlReader API, ... implementations are now broken, because they don't supply this new method. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: N1298 - try/finally for C
    ... Do you mean that "struct throwInfo" should be optional? ... that exception handling would be supported only on implementations ... If the standard mandates an integer as throw argument, ... should be an integer wide enough to encode a pointer if necessary. ...
    (comp.std.c)