Agiltohr
Agiltohr

Reputation: 125

How would I approach a function lookup-table with member functions of different classes?

I am being passed an array with values that I need to pass on to a few objects to store them. The array is two-dimensional of the form

{{int ID, int iNewValue}, ...}

I do not know which or how many values are updated but the ID is unique and doesn't change. I am told the ID <-> value pair once so I could just use a massive switch statement to check the ID and pass the value to the correct object and correct setter function. I thought I could make it more efficient and convenient and use a lookup-table where the index is the ID and the element is a pointer to the correct member function:

for (int i = 0; i < iNewValueLength; i++)
{
    int ID = arrayNewValues[i][0];
    int iNewValue = arrayNewValues[i][1];
    (object.*lookup_table[ID])(iNewValue);
}

However, I am running into two issues:

  1. I have multiple objects per class so I would need to be able to have individual entries in my lookup_table for different individual objects (even though they have the same functions). As an example, I have different humans and get updates to their height so I save the height setter function of each individual "human-object" and pass the updated height value to the correct object when I get an update. lookup_table[5] might point to the height setter function of human-object number 2. I am having trouble understanding how to implement this, I've stumbled over this question. Is this what I want or is there another way?

  2. I have multiple different classes so I can't put it all inside one lookup table (or can I?). Since I have no control over how the IDs are assigned which means I cannot they assume they are in order and do something like

if (ID < 10)        (object1.*lookup_table_object1[ID])(iNewValue);
else if (ID < 20)   (object2.*lookup_table_object2[ID])(iNewValue);
...

What should I do?

Thanks in advance for any help or pointers in the right direction!

Upvotes: 1

Views: 910

Answers (1)

Daniel Langr
Daniel Langr

Reputation: 23497

Consider the following exemplary classes that have some member functions accepting int arguments:

struct X {
  void f1(int i) const { std::cout << "X::f1(" << i << ")\n"; }
  void f2(int i) const { std::cout << "X::f2(" << i << ")\n"; }
};

struct Y {
  void f1(int i) const { std::cout << "Y::f1(" << i << ")\n"; }
  void f2(int i) const { std::cout << "Y::f2(" << i << ")\n"; }    
}; 

Now, suppose you have some objects of these classes:

X x;
Y y;

To accomplish your goal, you can create a lookup table with value type std::function<void(int)>:

std::map<int, std::function<void(int)>> m; 

Then, you can populate such a lookup table with lambdas (or use std::bind in the old way) that represent particular combinations of objects (possibly different objects of different classes) and their member functions:

m[1] = [&x](int i){ x.f1(i); };
m[2] = [&x](int i){ x.f2(i); };
m[3] = [&y](int i){ y.f1(i); };
m[4] = [&y](int i){ y.f2(i); };

Finally, to invoke these functions:

m[3](12);
m[2](-1);

Which outputs:

Y::f1(12)
X::f2(-1)

Live demo: https://wandbox.org/permlink/GGPaNJ15EIm9g5gy.

Just beware of possible dangling references in lambdas. The referenced objects generally need to exist as long as the entries in the lookup table are linked to them.

Upvotes: 1

Related Questions