Get Pointer to Object from Pointer to Some Member

Get pointer to object from pointer to some member

If you are sure that the pointer is really pointing to the member b in the structure, like if someone did

Thing t;
some_function(&t.b);

Then you should be able to use the offsetof macro to get a pointer to the structure:

std::size_t offset = offsetof(Thing, b);
Thing* thing = reinterpret_cast<Thing*>(reinterpret_cast<char*>(ptr) - offset);

Note that if the pointer ptr doesn't actually point to the Thing::b member, then the above code will lead to undefined behavior if you use the pointer thing.

Get a pointer to object's member function

You cannot, at least it won't be only a pointer to a function.

Member functions are common for all instances of this class. All member functions have the implicit (first) parameter, this. In order to call a member function for a specific instance you need a pointer to this member function and this instance.

class Some_class
{
public:
void some_function() {}
};

int main()
{
typedef void (Some_class::*Some_fnc_ptr)();
Some_fnc_ptr fnc_ptr = &Some_class::some_function;

Some_class sc;

(sc.*fnc_ptr)();

return 0;
}

More info here in C++ FAQ

Using Boost this can look like (C++11 provides similar functionality):

#include <boost/bind.hpp>
#include <boost/function.hpp>

boost::function<void(Some_class*)> fnc_ptr = boost::bind(&Some_class::some_function, _1);
Some_class sc;
fnc_ptr(&sc);

C++11's lambdas:

#include <functional>

Some_class sc;
auto f = [&sc]() { sc.some_function(); };
f();
// or
auto f1 = [](Some_class& sc) { sc.some_function(); };
f1(sc);

Obtaining a pointer-to-member from addresses of an object and its member

Using visit_struct, you may first add reflection:

struct Point { double x, y, z; };

VISITABLE_STRUCT(Point, x, y, z);

Then visit your struct:

template <typename C, typename T>
struct MemberPtrGetter
{
constexpr MemberPtrGetter(const C& c, const T& field) : c(c), field(field) {}

// Correct type, check reference.
constexpr void operator() (const char* name, T C::*member) const
{
if (&(c.*member) == &field)
{
res = member;
}
}

// other field type -> ignore
template <typename U> constexpr void operator() (const char* , U C::*member) const {}

const C& c;
const Member& field;
Member C::* res = nullptr;
};

template<typename C, typename T>
constexpr T C::* obtain_member_ptr(const C& c, const T& field)
{
MemberPtrGetter<C, T> visitor{c, field};
visit_struct::apply_visitor<C>(visitor);
return visitor.res;
}

Get pointer to enclosing instance from member pointer

You cannot do this using well-defined C++ as casting between unrelated types is undefined behaviour.

In reality, you'll probably get away with assuming that the address of the first member of a class is the same as the address of the class offset by the size of a pointer on your system. (This pointer being the implementation of your v-table and that's reasonably consistent across C++ implementations.) Then, if you make some assumptions about the packing of the data members, then you make manual adjustments to your pointer to move from one data member to another. offsetof is another technique and can help you here, but it's still not well-defined in your context.

Either litter your source code with specific compiler assertions (as you are restricting portability), or adopt a different technique. I'd certainly adopt the latter.

Here's some very bad code which shows you how to do it. Consider

struct Foo
{
virtual ~Foo(){}; /*introduce a v-table*/
int n;
};

And,

  Foo foo;
foo.n = 0xdeadbeef; // To test
int* p = &foo.n; // Suppose this is our pointer.
char* pp = (char*)(void*)p; // This cast is undefined behaviour.
pp -= 8; // Skip over 64 bit v-table. More undefined behaviour.
Foo* ph = (Foo*)(pp); // Yet more undefined behaviour.

ph points to a Foo instance.

Pointer to class data member ::*

It's a "pointer to member" - the following code illustrates its use:

#include <iostream>
using namespace std;

class Car
{
public:
int speed;
};

int main()
{
int Car::*pSpeed = &Car::speed;

Car c1;
c1.speed = 1; // direct access
cout << "speed is " << c1.speed << endl;
c1.*pSpeed = 2; // access via pointer to member
cout << "speed is " << c1.speed << endl;
return 0;
}

As to why you would want to do that, well it gives you another level of indirection that can solve some tricky problems. But to be honest, I've never had to use them in my own code.

Edit: I can't think off-hand of a convincing use for pointers to member data. Pointer to member functions can be used in pluggable architectures, but once again producing an example in a small space defeats me. The following is my best (untested) try - an Apply function that would do some pre &post processing before applying a user-selected member function to an object:

void Apply( SomeClass * c, void (SomeClass::*func)() ) {
// do hefty pre-call processing
(c->*func)(); // call user specified function
// do hefty post-call processing
}

The parentheses around c->*func are necessary because the ->* operator has lower precedence than the function call operator.

pointer to object == pointer to first member?

There are no references involved in your code. Don't confuse the "address-of" operator (also &) with references.

Your condition returns true because in this case it happens that the object starts in the same place in memory as its first (and only) field. That's the case i.e. for so-called POD (plain-old-data) objects, but it's not always true.

For example it's likely for the condition to be false if your class contains any virtual functions. Don't depend on it.

How get the class (object type) from pointer to method

Try this:

template<class T>
struct MethodInfo;

template<class C, class R, class... A>
struct MethodInfo<R(C::*)(A...)> //method pointer
{
typedef C ClassType;
typedef R ReturnType;
typedef std::tuple<A...> ArgsTuple;
};

template<class C, class R, class... A>
struct MethodInfo<R(C::*)(A...) const> : MethodInfo<R(C::*)(A...)> {}; //const method pointer

template<class C, class R, class... A>
struct MethodInfo<R(C::*)(A...) volatile> : MethodInfo<R(C::*)(A...)> {}; //volatile method pointer


Related Topics



Leave a reply



Submit