Consider: struct T {
int x;
int y;
};
struct S {
int a;
int b;
T my_t;
};
Consider further the following function:
void Modify(S * ps, int S::*int_mem_ptr) {
ps->*int_mem_ptr = 42;
}
I can get a member pointer to the 'a' of S and the 'b' of S by:
int S::*pa = &S::a;
int S::*pb = &S::b;
S s;
Modify(&s, pa);// after which, s.a == 42
Modify(&s, pb);// after which, s.b == 42
I now want in to get an S-based member pointer of type 'int S::*' to the x of my_t. I'd like to do:
int S::*px = &S::my_t.x; // <-- compiler complains.
S s;
Modify(&s, px); // after which s.my_t.x == 42
Although my_t.x is not a direct int member of S, it certainly is contained by S. However, my compiler complains about the syntax. Is what I'm attempting even legal C++? I know I can hack my way around this with the appropriate offsetof hacks, but I'd like to do it portably if possible.
S::my_t is not a static member, so you need an instance of the class to access it.
I'm pretty sure 'int S::*' doesn't make sense as a type. What exactly is it supposed to mean?
@helios:
int S::* is as johnkal described - it is a pointer to a (data) member of S whose type is int.
@johnkal
What I don't understand is why you are messing around with pointers to members? A pointer to T::x would have type int T::*. Why not just pass pointers to ints?
I think that's the most ridiculous language construct I have seen so far. I mean, seriously. A pointer to a member of T of type T2? Whoever thought of that deserves to be punched in the back of the head.
jsmith: I'm writing an an interpreter that mimics the behaviour of old real-mode x86 programs. Think of S as a segment, and T as a struct in that segment. The int S::* corresponds to a "segment offset to int" in real-mode parlance.
Since the storage for my_t.x lives inside of S, there is an argument for being able to construct an int S::* member pointer to my_t.x. It just seems like there is no support for it in the language. Obviously, I can work around this issue by using offsetof(S, my_t.x), and then casting the resulting size_t to an int S::* , but that is non-portable.
@helios: Pointers to data members have very limited use in C++, I agree. However, the one thing that pointers to (data) members can provide is the safebool idiom. Pointers to member functions have a lot of use: in my project, we use them to register callback functions for various purposes.
@johnkal: In fact, doing the casting as you suggest probably won't work at all. The reason is because, on many platforms, an int* is a 32-bit value, but pointers to members are typically six or eight bytes.
I think you might be trying to use C++'s type system a bit too much... I understand what you are trying to model. But by using the type system you are limited what you, as the programmer of the interpreter, can do, not what the user of the interpreter can do.