Re: Pointer to "base" type - what does the Standard say about this?
- From: Stephan Beal <sgbeal@xxxxxxxxxxxxxx>
- Date: Thu, 6 Nov 2008 07:08:14 -0800 (PST)
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, whichthe 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!
.
- References:
- Pointer to "base" type - what does the Standard say about this?
- From: Stephan Beal
- Re: Pointer to "base" type - what does the Standard say about this?
- From: Antoninus Twink
- Re: Pointer to "base" type - what does the Standard say about this?
- From: Jean-Marc Bourguet
- Re: Pointer to "base" type - what does the Standard say about this?
- From: Stephan Beal
- Re: Pointer to "base" type - what does the Standard say about this?
- From: Stephen Sprunk
- Re: Pointer to "base" type - what does the Standard say about this?
- From: Eric Sosman
- Re: Pointer to "base" type - what does the Standard say about this?
- From: Stephan Beal
- Pointer to "base" type - what does the Standard say about this?
- Prev by Date: Re: ShareWare vs Evaluation
- Next by Date: Re: ShareWare vs Evaluation
- Previous by thread: Re: Pointer to "base" type - what does the Standard say about this?
- Next by thread: Re: Pointer to "base" type - what does the Standard say about this?
- Index(es):
Relevant Pages
|