Matt
Matt

Reputation: 826

How to Access an Object's Variables/Methods using Another Variable

Suppose that I have a struct Node which contains x and y and I would like to create a vector of these Nodes.

struct Node {
    int x;
    int y;
    Node(int x, int y);
};

vector<Node *> nodes;

I would like to write various functions that work either on x or y. For example, I want to write a sort function that sorts the nodes vector by x coordinates and another one which sorts based on y.

It is definitely a better idea to write a single function that implements both sort_by_x and sort_by_y. I was thinking of writing a function which takes a bool like isX and performs the sorting accordingly. However, I would like to avoid writing the same code twice (once for x and once for y). I want to write a single piece of code that performs the corresponding sorting. I tried to implement this using the following code, but it is not valid in C++ (because it expects c to be one of the variables in Node).

void mySort(vector<Node *> &nodes, bool isX) {
    char c;
    if (isX) {
        c = 'x';
    }
    else {
        c = 'y';
    }

    // some code
    nodes[i]->c // if c == 'x', x will be used, otherwise  y.
}

Would you please let me a workaround to rewrite the above code or some other way of implementing the same functionalities based on different variables?

Upvotes: 3

Views: 85

Answers (3)

flogram_dev
flogram_dev

Reputation: 42858

You don't have to write your own function to do the sorting. The standard library already has a generic sort function. You can use it like this:

auto x_comparator = [](auto a, auto b) { return a->x < b->x; }
auto y_comparator = [](auto a, auto b) { return a->y < b->y; }

std::sort(nodes.begin(), nodes.end(), x_comparator); // sort by x
std::sort(nodes.begin(), nodes.end(), y_comparator); // sort by y

Upvotes: 1

Alan Stokes
Alan Stokes

Reputation: 18974

You can use a pointer to member here:

int Node::*m;
if (isX) {
    m = &Node::x;
}
else {
    m = &Node::y;
}

// some code
nodes[i]->*m

The syntax is fairly ugly, but it does exactly what you're trying to do. If you have C++11 available an alternative would be to write simple lambda functions to return x or y and store them in a std::function; this is slightly less efficient, but less ugly and more general.

Upvotes: 4

jxh
jxh

Reputation: 70482

std::sort allows a comparator to be passed in as a third argument. You can change the behavior of the sort by using a different comparator for the x case and the y case.

std::sort(nodes.begin(), nodes.end(),
          [](const Node *a, const Node *b) -> bool {
              return a->x < b->x;
          });

Upvotes: 3

Related Questions