Search code examples
c++arraysgenericsstructmember-access

Optional logic when passing structures in c++


I am new too programming and am trying to pass an array of structures and an "option" to a function. I then want the function to be able to manipulate the data within the the array of the struct.

struct coordinates{
    int x;
    int y;
    int z;
}COORD;

The option parameter is an integer that will specify which part of the structure to manipulate.

  1. Manipulate x --- option = 0
  2. Manipulate y --- option = 1
  3. Manipulate z --- option = 2

An example of this is shown below. The function takes the array of structs and makes a 3 point moving average of the data-point specified data point. The issue I am having is that the program I am trying to build has 50+ members in each struct so writing out each if statement by hand is really tedious. What I am asking is if there is a more elegant solution???

#include <iostream>

struct coordinates{
    int x;
    int y;
    int z;
}COORD;

int main() {
    COORD points[10];

    // Initialising points
    for(int i = 0, i < 10, i++){ 
        points[i].x = 1;
        points[i].y = 2;
        points[i].z = 3;
    }
                            //(struct,startpoint,option)
    std::cout << movingaverage(&points,3,1); // Output
}

int movingaverage(COORD *data, int start_point, int option){

    if(option == 0) {
        // Assigns the "start" value of the sum value.
        sum = data[start_point]->x;
        sum = sum + data[start_point - 1]->x;
        sum = sum + data[start_point + 1]->x;
    }

    else if(option == 1) {
        // Assigns the "start" value of the sum value.
        sum = data[start_point]->y;
        sum = sum + data[start_point - 1]->y;
        sum = sum + data[start_point + 1]->y;
    }
    else if(option == 2) {
        // Assigns the "start" value of the sum value.
        sum = data[start_point]->z;
        sum = sum + data[start_point - 1]->z;
        sum = sum + data[start_point + 1]->z;
    }
    sum = sum / n;
    return sum; //Sum is the moving average
}

Solution

  • Also pointer to members are a possible solution; in combination with a template function, the members can be of different type. But, yes, the syntax is something strange:

    #include <iostream>
    #include <vector>
    using namespace std;
    
    /// calculate the sum of a given structure member in a vector:
    template <typename T, typename M>
    M membersum(vector<T> array, M (T::*mptr)) {
        M sum = 0;
        for (int i=0; i<array.size(); i++) {
            sum += (array[i].*mptr);
        }
        return sum;
    }
    
    struct Point {
        Point(int x, int y, float z): x(x), y(y), z(z) {}
        int x;
        int y;
        float z;
    };
    
    int main() {
        vector<Point> points;
        points.push_back(Point(1,2,3.8));
        points.push_back(Point(1,2,4.5));
        points.push_back(Point(1,2,1.7));
        // your code goes here
        cout << "sum x: " << membersum(points, &Point::x) << endl;
        cout << "sum y: " << membersum(points, &Point::y) << endl;
        cout << "sum z: " << membersum(points, &Point::z) << endl;
        return 0;
    }
    

    This example I created on ideone.com.