zwol: stylized sketch of a face in profile (Default)
[personal profile] zwol

In C you can totally do this.

  typedef struct { ... } S;
  typedef struct { ...; S s; ... } T;

  /* ESS assumed to be contained in a T.  */
  T * TfromS(S * ess) {
    return (T *)(((char *)ess) - offsetof(T, s));
  }

But in C++, offsetof is not defined when its first argument is a “non-POD type” (approximately, “a type you couldn't have declared in C.”) The replacement for offsetof is the “pointer to member.”

But you can't do the above with a pointer to member.

So how the Belgium do you do it?

Date: 2008-07-18 01:55 am (UTC)
From: [identity profile] echristo.livejournal.com
I have no idea other than to use (maybe) the vtable. If you figure it out though I'm all ears.

Date: 2008-07-18 08:14 pm (UTC)

Date: 2008-07-18 05:16 am (UTC)
From: [identity profile] elsmi.livejournal.com
I usually solve these problems by googling around, getting annoyed, continuing to fail for a day or two, then asking ncm.

good compiler, no donut

Date: 2008-07-18 08:52 am (UTC)
From: [identity profile] tkil.livejournal.com
On the one paw, the C++ compiler is within its rights to tell you that's complete rubbish: there's no way of guaranteeing that every S is in a T (if it were, it would be a subclass or member), so type safety dictates that you're not to do that.

Then reality comes in.

Anyway, a google search earlier came up with this gem:
http://quantumreference.blogspot.com/2008/03/making-c-macro-offsetof-work-with-c.html

I haven't tried it myself, but it seems that a sufficient number of reinterpret_casts and possible a static dummy instance should also work.

(Or, if every S really is in a T, then just teach S about its containing T. But in this case, I'm presuming that you're mostly trying to port over an existing code base, yes?)

Good luck.

Re: good compiler, no donut

Date: 2008-07-18 03:38 pm (UTC)
From: [identity profile] zwol.livejournal.com
As it happens, every S is indeed in a T. Having T be a subclass of S is inappropriate, for reasons which are too complicated to get into here. I'm not sure what you have in mind when you say "just teach S about its containing T"...?

Re: good compiler, no donut

Date: 2008-07-18 07:11 pm (UTC)
From: [identity profile] tkil.livejournal.com
As it happens, every S is indeed in a T.

Yeah, but since C++ is only looking at a single function whose argument is an S, it can't know that.

I'm not sure what you have in mind when you say "just teach S about its containing T"...?

The most straightforward way would be to add a pointer-to-T to the structure S. Downside is that it increases the size of S.

This thread is interesting: http://coding.derkeiler.com/Archive/C_CPP/comp.lang.cpp/2005-01/1105.html

Other random thoughts:

* You can't do it as a compile-time constant, due to virtual inheritance (I think that's the problem). You would have to traverse vtables at runtime.

* Try putting functions that need to do this in a C file with "C" linkage? If everything involved is "mostly a POD", then that might work well enough.

Really, though, it sounds like C++ might not be the right fit for this, if you're not free to use it properly (and "no-rtti" is often an indicator of exactly that).

Good luck.

Date: 2008-07-19 02:15 am (UTC)
From: [identity profile] elsmi.livejournal.com
Actually, isn't the reason for this restriction that if the T that contains your S is actually an instance of a subclass of T, maybe with some MI or whatever thrown in, the offset might be different? So what you want is genuinely impossible in general (and in particular, might work fine now but bite someone much later who innocently subclasses something), not just the C++ committee thumbing its nose at you for fun?

Of course, I'm guessing by now you've come up with some other approach, which might be for the best anyway...

April 2017

S M T W T F S
      1
2345678
9101112131415
16171819 202122
23242526272829
30      

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 3rd, 2026 04:24 am
Powered by Dreamwidth Studios