2

With a class definition, an object pointer and a pointer-to-member, it is possible to obtain an absolute pointer to that member:

class X {
public:
    int a { 0 };
    int b { 1 };
    int c { 2 };
};
X x;
X* xptr = &x;
int X::* pointer_to_member = &X::b;
int* absolute_pointer = &(xptr->*pointer_to_member);    // want to invert this line
std::cout << *absolute_pointer << std::endl;            // prints 1

I am looking for the inverse of the line before the last line of my sample code: Having an absolute_pointer pointing to some member of some object and a pointer_to_member to the same member of that object type, is it possible to recover the pointer to the object itself?

I am aware, that the trick can be done "C-style" with a few reinterpret_cast()s and offsetof. But is there a cleaner way to do it, like an official language feature or at least an official macro?

Artyer
  • 31,034
  • 3
  • 47
  • 75
Kai Petzke
  • 2,150
  • 21
  • 29
  • 1
    Not in general. With virtual inheritance, the member may even be located outside the region of memory occupied by the object. Pointer-to-member is more than just an offset from the beginning of the object. – Igor Tandetnik Mar 25 '23 at 20:07
  • It is possible to construct two values `X* xptr1` and `X* xptr2` so that `xptr1 != xptr2` but `&xptr1->*pointer_to_member == &xptr2->*pointer_to_member` , Clearly then the operation is irreversible. – Igor Tandetnik Mar 25 '23 at 20:14
  • 1
    @Artyer Yes, you are right and I am wrong. What I had in mind doesn't in fact work. I still don't know how to reverse the indirection through a pointer-to-member, but it no longer appears obviously impossible to me. It likely would have to rely on implementation-specific details though. – Igor Tandetnik Mar 25 '23 at 20:56
  • Potential duplicate: https://stackoverflow.com/questions/63094408/can-i-get-reference-of-an-object-with-address-of-member-variable-in-c. Sadly the answer is... not really. – PBS Mar 26 '23 at 05:29
  • @IgorTandetnik Can you write an example as an answer? – user3840170 Mar 26 '23 at 06:44
  • @IgorTandetnik I assume you think of code like this: `struct Comb : public A, public B {}; int Comb::*ptrComb = &Comb::A::a; int B::*ptrB = static_cast(ptrComb);`. But even in such cases, there is an original unambigious complete object (here of type `Comb`), that both the base of the pointer to member and the actually pointed to item are part of. So it is still a simple offset, even though it may be negative or larger than the size of the downcasted to object. – Kai Petzke Mar 26 '23 at 06:53
  • No, what I had in mind was a class that derives from `X` twice, while `X` has a virtual base class (a diamond-shaped hierarchy), and a pointer-to-member actually points to a data member within that virtual base. But it turns out C++ doesn't allow forming a pointer to member of a virtual base class. – Igor Tandetnik Mar 26 '23 at 13:28
  • @IgorTandetnik Forming a pointer to a member of a virtual base class is possible, but it is not possible to downcast that to a pointer to a member of a derived class of that base class, even, if that derived class is `final`, which should actually take away all ambiguities again. Seems like pointer-to-members are undersupported in many ways in C++. – Kai Petzke Mar 26 '23 at 17:42
  • @KaiPetzke: It actually can be said to be a deliberate design choice: preventing movement upward through a subobject hierarchy (you can’t even do it for arrays!) allows certain optimizations based on reachability. – Davis Herring Mar 26 '23 at 18:29

0 Answers0