I am trying to generalize the functions filterX()
and filterY()
in the following class Table
to function filter()
.
A member function requires a pointer to the object instance. That is, think of getX
as string Row::getX(const Table *this)
. You need to bind
the member function with an instance placeholder.
E.g. using tr1,
vector<int> vx = t.filter("x1", std::bind(&Row::getX, std::placeholders::_1));
The binding creates a functor that takes in a Row
object, assuming that your filter function is correctly defined. You should show code for filter
. I presume it should be:
template <class function>
vector<int> Table::filter(const string &s, function f)
{
vector<int> result;
for (vector<Row>::const_iterator it = d_table.begin(), tEnd = d_table.end();
it != tEnd; ++it)
{
if (s == f(*it)) result.push_back(it->getVal());
}
return result;
}
Here is how to do it by using pointer to member functions:
// helper to avoid type nightmare;
typedef string (Row::* GetterP)() const;
class Table
{
public:
void add(string x, string y, int val);
// Define a templated function that can be called with GetX or GetY
template <GetterP getter>
vector<int> filter(string s)
{
int i = (d_table[i].*getter)(); // how to use getter in filter
}
private:
vector<Row> d_table;
};
// Usage:
Table t;
t.filter<&Row::GetX>("");
Modify your code here:
public:
void add(string x, string y, int val);
vector<int> filter(string s, string (Row::*)() const);
private:
...
Here:
vector<int> Table::filter(string s, string (Row::*f)() const)
{
vector<int> result;
vector<Row>::iterator it;
for(it = d_table.begin(); it != d_table.end(); ++it) {
if((*it.*f)() == s) {
int val = it->getVal();
result.push_back(val);
}
}
return result;
}
And here:
int main()
{
...
vector<int> vx = t.filter("x1", &Row::getX);
vector<int> vy = t.filter("y2", &Row::getY);
...
Here is the syntax for the way you want:
vector<int> Table::filter(string s, string (Row::*get)() const)
{ //^^^^^^^^^^^^^^^^^^^^^^^^^^^ member pointer
...
if(((*it).*get)() == s) { // call using the (*it). and not it->
...
}
Call it as:
vector<int> vx = t.filter("x1", &Row::getX);
vector<int> vy = t.filter("y2", &Row::getY);
If you want to use explicit PMF ( or at least see how they are used):
Declare the PMF type:
class Row
{
public:
typedef string (Row::*getFilter)() const;
// etc.
};
class Table
{
public:
// Call it like this:
vector<int> pmf_filterX(string s)
{
return filter(s, &Row::getX);
}
private:
// Use it like this:
vector<int> filter(string s, Row::getFilter f)
{
vector<int> result;
vector<Row>::iterator it;
for(it = d_table.begin(); it != d_table.end(); ++it)
{
const Row& row = *it;
if ((row.*f)() == s)
{
int val = it->getVal();
result.push_back(val);
}
}
return result;
}
};