pointer to member function

前端 未结 5 1953
醉梦人生
醉梦人生 2021-01-20 13:56

I am trying to generalize the functions filterX() and filterY() in the following class Table to function filter().

相关标签:
5条回答
  • 2021-01-20 14:34

    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;
    }
    
    0 讨论(0)
  • 2021-01-20 14:38

    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>("");
    
    0 讨论(0)
  • 2021-01-20 14:47

    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);
    
        ...
    
    0 讨论(0)
  • 2021-01-20 14:56

    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);
    
    0 讨论(0)
  • 2021-01-20 14:56

    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;
        }
    };
    
    0 讨论(0)
提交回复
热议问题