Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

passing a boost::function to a template; what class is boost::function

I need to pass a distance-function to a template. Therefore I use boost::function and boost::bind. But I do not understand what I have to pass for class Distance:

template<class DataType, class Point, class Distance>
class CoverTree
{
    Distance distance;
    ...
    public:
     CoverTree(const Distance& distance) : max_level(default_max_level), min_level(default_max_level), distance(distance) {}
    ...
}

the example by the author of the template looks like this:

float euclidian(const std::vector<float>& p1, const std::vector<float>& p2)
{
    ...
}
int main(int argc, char** argv)
{
    CoverTree<float, std::vector<float>, float (*const)(const std::vector<float>&, const std::vector<float>&)> tree(&euclidian);
    ...
}

Now this is my main:

int main(int argc, char** argv)
{
    AllData myData;
    boost::function<float (const vector<Frame>::const_iterator&, const vector<Frame>::const_iterator&)> j_dist;
    j_dist = boost::bind(&AllData::jaccard_distance, myData, _1, _2);
    myData.AddData("C:\\...");
    cout<<j_dist(myData.DATAx.begin()+20, myData.DATAx.begin()+40)<<endl; //works fine
    CoverTree<float, vector<Frame>::const_iterator, ???> tree(&j_dist);
    ...
}

At first, can somone explain me what (*const) means or where I can read about this?
And second: I think I wrote everything you need, to tell what to write for ??? but I don't get it.
I already tried:

boost::function<float (const vector<Frame>::const_iterator&, const vector<Frame>::const_iterator&)

and

float (*const) (const vector<Frame>::const_iterator&, const vector<Frame>::const_iterator&)

but this was nice try and error :)

like image 576
user__42 Avatar asked Oct 22 '22 22:10

user__42


1 Answers

At first, can somone explain me what (*const) means or where I can read about this?

In the author's example the distance function is:

float euclidean(const std::vector<float>&, const std::vector<float>&);

The argument passed to the CoverTree constructor is the address of that function i.e. &euclidean, which is a function pointer of type

float (*)(const std::vector<float>&, const std::vector<float>&)

The template parameter for CoverTree is simply a const-qualified version of that type. Due to the peculiar "inside out" declarator syntax for functions in C and C++, a const pointer to that function type is declared as:

float (* const)(const std::vector<float>&, const std::vector<float>&)

This is analogous to a const pointer to int, which is declared as:

int* const

In your case, you got the type right, it's:

boost::function<float (const vector<Frame>::const_iterator&, const vector<Frame>::const_iterator&)

Let's use a typedef to refer to that:

typedef boost::function<float (const vector<Frame>::const_iterator&, const vector<Frame>::const_iterator&) distance_func;

but the problem is that you are not passing an argument of that type, you're passing a pointer to that type:

CoverTree<float, vector<Frame>::const_iterator, distance_func> tree(&j_dist);
                                                                    ^^^^^^^

You can see this won't work by doing:

distance_func f = &j_dist;  // ERROR! cannot convert distance_func* to distance_func

The answer should be to simply to pass an argument of the correct type:

CoverTree<float, vector<Frame>::const_iterator, distance_func> tree(j_dist);
                                                                    ^^^^^^
like image 192
Jonathan Wakely Avatar answered Oct 27 '22 20:10

Jonathan Wakely