1

How does one go about passing a struct member identifier to a function such that the function can apply an operation to that specified member? The below code example should highlight what I am trying to achieve.

struct _struct {
    int a = 0;
    int b = 0;
};
_struct test[5];

void printVar(int index, ??? member) {
    // Print specified member at array element
    printf(test[index].member);
};

int operation(??? member) {
    // Some operation applied to specified member of all array elements
    // eg. Averaging all the readings contained in test[].a
    int total = 0;
    for (int i = 0; i < 5; i++) {
        total += test.member;
    };
    return total / 5;
};

The closest I have found to a solution is described at the below link, whilst the principle is sound in its application it doesn't appear to be the best possible implementation. http://cplusplus.com/forum/beginner/45268/

2
  • You could use a std::map or std::unordered_map instead of a struct, and then pass the desired key as the member identifier. Alternatively, you could pass a std::function that fetches the desired member from the an argument of type _struct. Commented Feb 20, 2021 at 12:01
  • If I understand it correctly, you want to have global array test and pass either member a or b to operation, so that it returns sum of all a or b from the array? Commented Feb 20, 2021 at 12:13

2 Answers 2

3

This is what "pointer to member" is for.

struct _struct {
    int a = 0;
    int b = 0;
};
_struct test[5];

void printVar(int index, int _struct::* member) {
    // Print specified member at array element
    printf("%d\n",test[index].*member);
};

int operation(int _struct::* member) {
    // Some operation applied to specified member of all array elements
    // eg. Averaging all the readings contained in test[].a
    int total = 0;
    for (int i = 0; i < 5; i++) {
        total += test[i].*member;
    };
    return total / 5;
};


int main(){
    printVar(1,&_struct::b);
    operation(&_struct::a);
    return 0;
}
Sign up to request clarification or add additional context in comments.

3 Comments

That is exactly the solution I needed, thankyou! Funny how no amount of googling reveals what you want sometimes. I had actually even tried what you suggested minus the "int" datatype of the pointer.
@Scheff Would have done so earlier if the option had been there, I upvoted instead.
@BranyonApel This might be caused by your rep. Once, I made a question and got an answer immediately, I had to wait 10 minutes but my rep. was already higher... ;-)
2

How about passing a std::function that returns the desired member from a given _struct? Like this:

#include <functional> // for std::function

struct _struct {
    int a = 0;
    int b = 0;
};
_struct test[5];

void printVar(int index, std::function<int(const _struct&)> getMember) {
    // Print specified member at array element
    printf("%d\n", getMember(test[index])); // note: added missing "%d"
};

int operation(std::function<int(const _struct&)> getMember) {
    // Some operation applied to specified member of all array elements
    // eg. Averaging all the readings contained in test[].a
    int total = 0;
    for (int i = 0; i < 5; i++) {
        total += getMember(test[i]); // note: added missing [i]
    };
    return total / 5;
};

You would use it like this:

int get_a(const _struct& s) { return s.a; }
int get_b(const _struct& s) { return s.b; }

int main()
{
    test[0] = {0,1};
    test[1] = {2,3};
    test[2] = {4,5};
    test[3] = {6,7};
    test[4] = {8,9};

    printVar(2, get_a); // prints value of test[2].a
    printVar(4, get_b); // prints value of test[4].b

    const int result_a = operation(get_a); // perform operation on the a members
    const int result_b = operation(get_b); // perform operation on the b members

    return 0;
}

Or, if you're familiar with lambdas, you can use them to define get_a and get_b instead of making them free-standing functions:

int main()
{
    test[0] = {0,1};
    test[1] = {2,3};
    test[2] = {4,5};
    test[3] = {6,7};
    test[4] = {8,9};

    const auto get_a = [](const _struct& s) { return s.a; };
    const auto get_b = [](const _struct& s) { return s.b; };

    printVar(2, get_a); // prints value of test[2].a
    printVar(4, get_b); // prints value of test[4].b

    const int result_a = operation(get_a); // perform operation on the a members
    const int result_b = operation(get_b); // perform operation on the b members

    return 0;
}

3 Comments

You even could use a lambda instead of get_a() and get_b(), e.g.: const int result_a = operation([](const _struct &s) { return s.a; });
@Scheff Yep, I was going to use a lambda but wasn't sure if the OP was familiar with them. Updated to add a version that defines them as lambdas.
Hi, thanks for your answer. Thats an interesting way to do it, however @PeterT has exactly the methodology I was chasing. Having to define the separate function for each new parameter you have to grab adds the extra step as such.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.