functors, and changin them "on the run"

Well let me first show the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <functional>
#include <cmath>

class generic_dis {
public:
	virtual double operator() (const std::pair<int,int>& p1,const std::pair<int,int>& p2) const =0;
};

class manhattan_dis : public generic_dis {
public:
	double operator() (const std::pair<int,int>& p1,const std::pair<int,int>& p2) const {
		return std::abs(p1.first - p2.first) + std::abs(p1.second - p2.second);
	}
};
class pythagoral_dis : public generic_dis  {
public:
	double operator() (const std::pair<int,int>& p1,const std::pair<int,int>& p2) const {
		return std::sqrt(double(sqr(p1.first-p2.first)+sqr(p1.second - p2.second)));
	}
protected:
	template <typename T>
	T sqr(const T& v) const  {
		return v * v;
	}
};
template <typename distance_func>
class Student {
public:
	Student(std::pair<int,int> _p1,std::pair<int,int> _p2,const distance_func& _pdis) : p1(_p1), p2(_p2), point_distance(_pdis)  {
		
	}
	std::pair<int,int> p1;
	std::pair<int,int> p2;
	double calc_distance() {
		return point_distance(p1,p2);
	}
	distance_func point_distance;
};

int main() {
	Student<manhattan_dis> S(std::make_pair(0,0),std::make_pair(1,1),manhattan_dis());
	S.point_distance = pythagoral_dis();
	std::cout << S.calc_distance() <<std::endl;
	system("pause");
}


This is a simplified idea of what I want:

I want to be able to create a structure which has a 'dynamic' distance function: and I want to be able to change that distance function after the object has be instantiated. Is this possible?
Sure, just store a reference (or a pointer if a Student is valid without the functor) to a generic_dis instance. The Student class does not need to be a template for this. Expect to have to work out a few compilier errors to get everything working, again. For example, you might get some kind of discards qualifiers error because of the Student constructor signature and I'm not sure you can just up and create a temporary in the assignment on line 43.

The main issue with this will be ownership of the generic_dis instance. In order to prevent the local distance functor from going out of scope, you could either: 1) use new and decide whether Student or the application should delete it, or 2) implement the Prototype pattern.

Aside from that, you might want to try using a template parameter for 'int', since there are many pairs that are all bound to it. main could use a return statement, too. ;)
Last edited on
lol, well again, this is just a "test case": however I don't really understand what you mean with this:

so I would make point_distance of the type "generic_dis" and then it should work (Basically changing all parameters from "distance_func" to "generic_dis")? - Cause it doesn't. (first of all it complains about generic_dis being a pure virtual function and unable to instantiate this: then it only executes "generic_dis" and thus at the line 43 "pythagoral_dis()" gets converted to generic_dis?


Thanks for the answer, but could you please write it a bit in example code? (PS: the Student class should be the ownership of the generic_dis function)..
Close but don't forget the reference/pointer part--it is the key.

Here is an example demonstrating the reference-to-base functionality:
1
2
3
4
5
6
7
8
9
10
    const generic_dis & point_distance;  // this must be set in the constructor
                                         // initialization list, it cannot be null

    //...

    manhattan_dis f1;
    pythagoral_dis f2;
  
    point_distance = f1;
    point_distance = f2;


Note that the example is just using references to locals, for simplicity. Remember, do not get discouraged; there will be compiler errors that you'll need to work through.
Last edited on
Topic archived. No new replies allowed.