1

Suppose I have this setup:

struct XView;
struct X
{
  ...
  XView  view;
};

Type XView is only used for this one field; it is internal too, so instantiating it from outside, i.e. using it for anything else is prohibited.

So, assuming any object of XView type is an X::view field, is it possible to find address of X from address of XView, staying fully within behavior defined by C++ standard and without type-punning? I.e. is it possible to do something like this:

void XView::some_function ()
{
  X&  this_x = some_computations_involving (this);
}

I can of course store a pointer, so this would become as trivial as x = *this->parent_x, but would like to do without one if possible.

EDIT: Note that I need an answer without type-punning involved, otherwise I'd rather use that "just store a pointer" solution.

  • @JaredC: I know about `offsetof`, but I'm not sure if I can use it in this case without some ugly `reinterpet_cast`. –  Mar 16 '13 at 19:40
  • Can't you use inheritance for this? Make `XView` a base class of `X` and you won't have to do any casting at all. – In silico Mar 16 '13 at 19:55
  • @Insilico: No, I have to be sure that `X x; x.view.do_stuff()` works for compatibility reasons. –  Mar 16 '13 at 19:56
  • You should've made `view` private and made a `x.get_view()` function. :-) But yeah that does make using inheritance a no-go. – In silico Mar 16 '13 at 19:57

2 Answers2

1

First approach is to make XView the first member of X, then you can do this:

void XView::some_function ()
{
   X & this_x = reinterpret_cast<X&>(*this);
}

Second approach is to use offset when XView is not the first member of the X.

Techinically speaking both of these approaches are same if there is no virtuality involved, only that the first approach is a special case (i.e when offset = 0) of the second approach which is the general case.

As for the edit, I think, without casting it is not possible. You have to store the pointer in XView, Or maintaining a map (or some other data structures) of pointers.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Please see edit. When I wrote about "defined behavior" I meant no type-punning as well, but I'm kinda rusty on C++ terminology and don't know if that was enough. Clarified in any case. (And I also have more than one view.) –  Mar 16 '13 at 19:44
  • *both...approaches are exactly the same* - not quite, using offsetof should cope with a pointer to the virtual dispatch table for X. – Tony Delroy Mar 16 '13 at 19:46
  • @doublep: Without casting it is not possible. You have to store the pointer in `XView`, or else create map of pointers. – Nawaz Mar 16 '13 at 19:46
  • @Nawaz: that's what I'm afraid of, but maybe I overlooked some solution with `static_cast`, which would be fine. –  Mar 16 '13 at 19:47
  • @doublep: Actually `reinterpret_cast` in this case is equivalent to a chain of *two* `static_cast` – Nawaz Mar 16 '13 at 19:49
  • @Nawaz: I don't see how. If you can rewrite your answer using `static_cast`s alone in a way compiler would accept, then that's exactly what I want. –  Mar 16 '13 at 19:50
  • 2
    @doublep: The C++ standard does actually explicitly allow for using `reinterpret_cast` to cast back-and-forth between a pointer to the object and a pointer to its first member, as long as they're both POD. Although in this case I don't see why you can't use inheritance. – In silico Mar 16 '13 at 19:50
  • @Insilico: Oh, that's good. Can you refer to exact paragraph? I have more than one view, but perhaps I could use it at least for one. –  Mar 16 '13 at 19:51
  • 1
    @doublep: See this : http://stackoverflow.com/questions/5025843/why-do-we-have-reinterpret-cast-in-c-when-two-chained-static-cast-can-do-its ... Also, I've seen @Johannes speaking of `reinterpret_cast` being equivalent to a chain of two `static_cast` in such cases, is per the Standard. – Nawaz Mar 16 '13 at 19:52
  • @Nawaz: Thank you. I'll wait if a more generic solution appears (miraculously), else will accept this. –  Mar 16 '13 at 19:54
  • 2
    @doublep: It's section 9.2 paragraph 17, but the caveat is that the objects in question has to be plain old data types. – In silico Mar 16 '13 at 19:54
  • @Insilico also the alignment requirements cannot be made stricter in any given cast – Stephen Lin Mar 16 '13 at 20:29
0

The most important thing is whether you really need accessing the parent object from child object and not vice-versa.

I would suggest you using some kind of bi-directional linked list or something like this.

Could your code be refactored to be more object-oriented? (and possibly using the inheritance (and calling the parent by using the super::some_function...)

  • I just offload part of the interface from the main object to views. And actually I need that for compatibility anyway, so changing interface is out of question. –  Mar 16 '13 at 19:48