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_t
s. 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?
f
is already a pointer to the desired member, so just pass that:&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.