Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template function to access struct members

I have a struct which contains other structs as well as primative data types. I'd like to be able to access each member including members of the structs contained within the main struct with a template function.

For example:

struct B {
    int y;
    int z;
};

struct A {
    int x;
    B b;
};

template <typename TMember>
bool doSomething(A *a, TMember member) {

    a->*member = 5;  // some code accessing member

}

// Then access it with:

doSomething(&myA, &A::x);

// and likewise

doSomething(&myA, &A::b.y);

However the 2nd will not compile and throw a "object missing in reference to" error. I assume its because A does not have a member b.y?

Is there anyway to get the functionality that I want or will coding a different function be required?

(Note this is just an example and the code that I have contains a larger structure and will save me more time than just writing a second function.)

Thanks!

like image 448
Chris Hunter Avatar asked Sep 15 '25 14:09

Chris Hunter


1 Answers

You can't make a pointer to a pointer to a member (it's forbidden by the language). However, you can keep accessing pointers to members all the way down.

If we generalize access with a recursive function that keeps invoking pointers to members:

template <typename C, typename T>
decltype(auto) access(C& cls, T C::*member) {
    return (cls.*member);
}

template <typename C, typename T, typename... Mems>
decltype(auto) access(C& cls, T C::*member, Mems... rest) {
    return access((cls.*member), rest...);
}

Then we can write doSomething to take an arbitrary amount of pointers:

template <typename... Members>
void doSomething(A *a, Members... mems) {
    access(*a, mems...) = 5;
}

And call it:

A myA;
doSomething(&myA, &A::x);
doSomething(&myA, &A::b, &B::y);
like image 62
Barry Avatar answered Sep 17 '25 04:09

Barry