2013-09-22 3 views
6

То, что я хочу сделать, это:Отправка имя функции к функции

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; 
    } 

} 

пример:

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; 
} 

Почему?

  1. это спасло бы меня, чтобы написать функцию типа: среднее значение суммы. среднее значение макс. среднее значение min , которые являются довольно похожими функциями.
  2. , как она кодируется B< B< A> > работает

Что я пробовал?

  • указатель функции
  • S1:

    typedef double (A::*MyFunctionf)(double, double); 
        typedef double (B<A>::*MyFunctionff)(double, double); 
        typedef double (B<B<A> >::*MyFunctionfff)(double, double); 
    
    • это работает. Проблемы:
      • это не красиво объявить 3-4 ЬурейиХ функциональный указатель
      • , если я хочу, чтобы написать функцию внутри B, отправившего указателя функции будут жестко и только 1 из 3 ЬурейиХ могут быть жестко закодированным. Значение: он не работает на каждые случаях
  • S2 (на основе Template typedefs - What's your work around?):

    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; 
        } 
    

    пример:

    // 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); 
    

Я не знаю, откуда эта проблема. Я также пробовал Boost.Function

+0

Каковы аргументы a и b для sum() и max() в ваших двух классах шаблонов A и B? –

+0

@ Konrad - пожалуйста, восстановите C++ для названия, так как вопрос действительно не имеет смысла без спецификации языка - это не просто тег, это фундаментальная часть значения. –

+0

@ChrisStratton Теги являются фундаментальной частью смысла вопросов, особенно для больших языковых. Они не «просто» ничего! – Yakk

ответ

2

Да, это возможно.

Вы ищете указатели для участников. Синтаксис не очевидно, однако:

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); } 
}; 

Это класс, который определяет несколько методов (sum и 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; 
    } 
}; 

Это класс с методом, который принимает указатель метода и который будет вычислять среднее значение результата вызова метода заостренный над элементами вектора.

Пример пропускания двух A методов:

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; 
} 
+0

Я действительно хочу сохранить классы, потому что мне нужно наследование. пример суммы и макета был составлен для упрощения того, что я намеревался сделать. спасибо !! – Setepenre

0

Решение С Boost.Функция

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; 
    } 

} 

пример

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

Рабочий пример ::

#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 << A.d(0, 0) << endl; 
    cout << A.c(0, 0) << endl; 

    return 0; 
} 
0

Общий C++ идиома делать такого рода вещи, чтобы передать функцию "объект" и принять в качестве параметра шаблона:

#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)); 
} 

Это очень общий подход, поскольку он не только принимает указатели на функции или указатели функций-членов, но и любой тип вызываемого объекта. Использование указателя функции-члена просто через std::mem_fn.

Смежные вопросы