如何通过函数指针递归调用类成员函数?

I'm writing a library to run certain algorithms on tree-like objects. I have an edge_t class that has const unsigned int data members edge_id and weight that serve, respectively, as the edge_t's unique identifier and the weight of the edge.

I have written tree_t and subtree_t classes in C++, both of which contain maps to pointers to edge_ts. Both tree_t and subtree_t are each derived from an abstract basic_tree_t class that contains all the functionality that tree-like objects are supposed to have, including the following methods:

// returns the sum of the weights of the edge_ts below the edge_t pointed to by edge_ptr
unsigned int basic_tree_t::weight(const edge_ptr) const

// returns the number of edge_ts below the edge_t pointed to by edge_ptr
unsigned int basic_tree_t::num_descendents(const edge_ptr) const

I'm writing some other code in which the user inputs a tree_t object, and the code has to iteratively sample a subtree_t from it, do some calculation, sample another subtree_t, do more calculation, and so on. To do the calculation the code needs to know the values of weight and num_descendents for every edge in each of these subtree.

To avoid calculating the same values repeatedly, each time I build a new subtree I'm creating std::map<unsigned int, unsigned int> weight_map and std::map<unsigned int, unsigned int> num_descendents_map, which map each edge_id of the subtree's edges to the values output by the respective member functions in basic_tree_t and then work with those. I wrote the following functions to populate these maps:

void populate_weight_map(subtree_t & S, edge_ptr & e, std::map<unsigned int, unsigned int> & weight_map)
{
        weight_map.insert(std::pair<unsigned int, unsigned int>(e->edge_id, S.weight(e)));
        for (auto & c : *(e->children))
                if (S.contains(c))
                        populate_weight_map(S, c, weight_map);
}

void populate_num_descendents_map(subtree_t & S, edge_ptr & e, std::map<unsigned int, unsigned int> & num_descendents_map)
{
        num_descendents_map.insert(std::pair<unsigned int, unsigned int>(e->edge_id, S.num_descendents(e)));
        for (auto & c : *(e->children))
                if (S.contains(c))
                        populate_weight_map(S, c, num_descendents_map);
}

Those are largely the same function, so I thought it would make more sense to write one function that takes a pointer to the relevant basic_tree_t member function as a fourth argument, something like this:

void populate_map(subtree_t & S, edge_ptr & e, std::map<unsigned int, unsigned int> & m, unsigned int (basic_tree_t::*f)(const edge_ptr) const)
{
        m.insert(std::pair<unsigned int, unsigned int>(e->edge_id, (S.*f)(e)));
        for (auto & c : *(e->children))
                if (S.contains(c))
                        populate_map(S, c, m, &basic_tree_t::*f); // ERROR ON THIS LINE!
}

但是,编译器在最后一行返回不透明错误:

error: expected unqualified-id
                    populate_map(S, c, m, &basic_tree_t::*f);
                                                         ^

What should the fourth argument to populate map be?

评论
  • uet
    uet 回复

    f is already a pointer to the desired member, so just pass that:

    populate_map(S, c, m, f);
    

    &basic_tree_t::*f makes no sense in that context. It looks like an attempt to declare a pointer to a data member, which isn't what you want anyway.