I have multiple classes C1, C2, etc, each has different members variables, ex: C1M1, C1M2, C2N1, C2N2. And I have a pointer to data that could be an object of C1, C2 based on initial bytes. Is there a way to write a method/template method to which I can specify, pointer to data, C1 and M1. And I can write logic on how to interpret how to read the data.
template<class C, class C::Member>
Member* Access(void* ptr) {
C* p = reinterpret_cast<C*>(ptr);
return &p->Member;
}
I have multiple classes C1, C2, etc, each has different members variables, ex: C1M1, C1M2, C2N1, C2N2. And I have a pointer to data that could be an object of C1, C2 based on initial bytes. Is there a way to write a method/template method to which I can specify, pointer to data, C1 and M1. And I can write logic on how to interpret how to read the data.
template<class C, class C::Member>
Member* Access(void* ptr) {
C* p = reinterpret_cast<C*>(ptr);
return &p->Member;
}
Share
Improve this question
edited Jan 30 at 7:52
pasha
asked Jan 30 at 7:42
pashapasha
2,11520 silver badges37 bronze badges
8
|
Show 3 more comments
3 Answers
Reset to default 7The shown code code in the question is unclear. A working example
template<class C, typename T, T C::*Member>
auto* Access(void* ptr) {
C* p = static_cast<C*>(ptr);
return &p->*Member;
}
If T
is known and fixed, for example int
template<class C, int C::*Member>
int* Access(void* ptr) {
C* p = static_cast<C*>(ptr);
return &p->*Member;
}
As you use version C++20, you might even shorten usage code
template <auto member>
auto* Access(void* ptr) {
return [&]<typename C, typename Ret, Ret C::* M>(std::integral_constant<Ret C::*, M>){
C* p = reinterpret_cast<C*>(ptr);
return &(p->*M);
}(std::integral_constant<decltype(member), member>());
}
With usage similar to
C1 c1;
*Access<&C1::C1M1>(&c1) = 42;
Demo
If you think it's really needed, you can do it by applying Pointers to members like this:
struct C1 {
int C1M1;
int C1M2;
};
struct C2 {
int C2N1;
int C2N2;
};
template <class C, int C::* M_PTR>
int* Access(void* ptr) {
C* p = reinterpret_cast<C*>(ptr);
return &(p->*M_PTR);
}
TEST(yyy, zzz) {
C1 c1{1, 2};
C1 c2{3, 4};
void* ptr1 = &c1;
void* ptr2 = &c2;
std::cout << *Access<C1, &C1::C1M2>(ptr1) << '\n';
std::cout << *Access<C2, &C2::C2N1>(ptr2) << '\n';
*Access<C2, &C2::C2N2>(ptr2) = 5;
std::cout << *Access<C2, &C2::C2N2>(ptr2) << '\n';
}
I assumed your member type is fixed as int
, if it's not, then you might need another template parameter, e.g.
template <class C, typename M, M C::* M_PTR>
M* Access(void* ptr) {
C* p = reinterpret_cast<C*>(ptr);
return &(p->*M_PTR);
}
C::Member
is a class member, how can it be a typeMember*
? – 3CxEZiVlQ Commented Jan 30 at 7:58