Sending the function name of the function

What I want to do:

class A { public: double sum(double a, double b); double max(double a, double b); } template <typename T> class B { std::vector<T> data; public: double sum (double a, double b); double max (double a, double b); double average( MyFunction, double a, dobule b) { double sum = 0; int n = data.size(); for ( int i = 0; i < n; i++) sum = sum + data[i].MyFunction(double a, double b) return sum / n; } } 

Example:

 double average( max, double a, double b) { double sum = 0; int n = data.size(); for ( int i = 0; i < n; i++) sum = sum + data[i].max(double a, double b) return sum / n; } 

Why?

  • it would save me to write a function like: average sum. average value max. average value min. which are pretty similar features.
  • encoding method B< B< A> > works

What have i tried?

  • function pointer
  • S1 :

      typedef double (A::*MyFunctionf)(double, double); typedef double (B<A>::*MyFunctionff)(double, double); typedef double (B<B<A> >::*MyFunctionfff)(double, double); 
    • It works. Problems:
      • It's not nice to declare a 3-4 typedef function pointer
      • if I want to write a function inside B that sent a pointer to a function, it will be hardcoded, and only 1 out of 3 typedef can be hardcoded. Meaning: It does not work for all cases.
  • S2 (based on typedefs templates - What is your job?:

      template <typename rtype, typename t> struct CallTemplate { typedef rtype (t::*ptr)(double, double); }; // the function becomes : template <typename T> template<typename rtype> double B<T>::average(CallTemplate<double, T> MyFunction, double a, double b) { double sum = 0; int n = data.size(); for ( int i = 0; i < n; i++) sum = sum + (data[i].*MyFunction)( a, b) return sum / n; } 

    Example:

      // makes an error "Myfunction was not declared" + " // dependent-name'{anonymous}::CallTemplate<double, A>::ptr' // is parsed as a non-type, but instantiation yields a type" CallTemplate<double, A>::ptr MyFunction = &A::max; Average(max, t, v); 

I do not know where this problem comes from. I also tried Boost.Function

+6
source share
3 answers

Yes it is possible.

You are looking for pointers for participants. However, the syntax is not obvious:

 struct A { double x, y; A(double x, double y) : x(x), y(y) {} double sum() { return x + y; } double max() { return std::max(x, y); } }; 

This is a class that defines a pair of methods ( sum and max ).

 template <typename T> struct B { std::vector<T> data; double average(double (T::*MyMethod)()) { double sum = 0; int n = data.size(); for (int i = 0; i < n; i++) sum = sum + (data[i].*MyMethod)(); return sum / n; } }; 

This is a class with a method that takes a method pointer and which will calculate the average value of the result of calling the specified method over the elements of the vector.

An example of passing two methods A is:

 int main(int argc, const char *argv[]) { B<A> b; b.data.push_back(A(1, 2)); b.data.push_back(A(3, 4)); b.data.push_back(A(5, 6)); std::cout << b.average(&A::max) << std::endl; std::cout << b.average(&A::sum) << std::endl; return 0; } 
+2
source

Solution with Boost.Function

 class A { public: double sum(double a, double b); double max(double a, double b); } template <typename T> class B { std::vector<T> data; public: double sum (double a, double b); double max (double a, double b); double average(boost::function<double (T*, double, double) MyFunction, double a, dobule b) { double sum = 0; int n = data.size(); for ( int i = 0; i < n; i++) sum = sum + MyFunction(&data[i], a, b) return sum / n; } } 

Example

 boost::function<double (A*, a, b)> MyFunction = &A::max; average(MyFunction, a, b); 

Working example ::

 #include <cmath> using namespace std; #include <vector> #include <boost/function.hpp> #define CallTemplate(returnvalue, FINClass) boost::function<returnvalue (FINClass*, double, double)> class zc { double n; double r; double p; public: zc(double nn, double rr, double pp):n(nn), r(rr), p(pp) {} double pv(double t, double v) { return p/ pow ( ( 1 + r + v), ( n - t) );} double d(double t, double v) { return (n - t); } double c(double t, double v) { return (n - t)*(n - t)+(n - t); } }; template <typename T> class Master { public: Master(){} std::vector<T> data; double pv(double t, double v) {CallTemplate(double, T) f = &T::pv; return sum(f, t, v);} double d(double t, double v) {CallTemplate(double, T) f = &T::d; return weightedAverage(f, t, v);} double c(double t, double v) {CallTemplate(double, T) f = &T::c; return weightedAverage(f, t, v);} double sum(CallTemplate(double, T) MyFunction, double t, double v) { double sum = 0; for( int i = 0, n = data.size(); i < n; i++) sum = sum + MyFunction(&data[i], t, v); return sum; } double weightedAverage(CallTemplate(double, T) MyFunction, double t, double v) { double sum = 0; double weight = 0; double buf =0; for( int i = 0, n = data.size(); i < n; i++) { buf = data[i].pv(t, v); sum = sum + buf; weight = weight + MyFunction(&data[i], t, v) * buf; } return weight/sum; } }; int main() { Master<zc> A; for (int i = 1; i < 10; i++) A.data.push_back(zc(i, 0.1, 100)); A.data.push_back(zc(10, 0.1, 1100)); cout << A.pv(0, 0) << endl; cout << Ad(0, 0) << endl; cout << Ac(0, 0) << endl; return 0; } 
0
source

The general C ++ idiom, to do such things, is to pass the “object” function and accept it as a template parameter:

 #include <algorithm> // definition of class A by user http://stackoverflow.com/users/320726/6502 // in answer http://stackoverflow.com/a/18944672/420683 struct A { double x, y; A(double x, double y) : x(x), y(y) {} double sum() const { return x + y; } double max() const { return std::max(x, y); } }; template <typename T> struct B { std::vector<T> data; template<class Function> double average(Function f) { double sum = 0; int n = data.size(); for (int i = 0; i < n; i++) sum = sum + f(data[i]); return sum / n; } }; #include <functional> int main() { B<A> b{ {{1.0, 42.0}, {2.0, 43.0}, {3.0, 44.0}} }; b.average([](A const& p){ return p.sum(); }); b.average(std::mem_fn(&A::sum)); } 

This is a very general approach because it not only accepts pointers to functions or pointers to member functions, but also any type of object being called. Using a member function pointer is simple with std::mem_fn .

0
source

Source: https://habr.com/ru/post/954349/


All Articles