Абстрактный
У меня есть класс, который хранит проблему оптимизации и запускает решатель этой проблемы. Если решатель не работает, я хочу рассмотреть подзадачу и решить ее, используя тот же решатель (и класс).
Введение
Задача оптимизации состоит из множества (математических) функций. Функции задачи определены вне класса, но функции подзадач определены внутри класса, поэтому они имеют разные типы (например, void (*)
и void (MyClass::*)
.
Сначала я думал, что могу привести функцию-член к типу указателя на функцию, не являющемуся членом, но обнаружил, что не могу. Поэтому ищу другой способ.
Пример кода
Пример кода для имитации моей проблемы:
#include <iostream>
using namespace std;
typedef void (*ftype) (int, double);
// Suppose foo is from another file. Can't change the definition
void foo (int n, double x) {
cout << "foo: " << n*x << endl;
}
class TheClass {
private:
double value;
ftype m_function;
void print (int n, double x) {
m_function(size*n, value*x);
}
public:
static int size;
TheClass () : value(1.2), m_function(0) { size++; }
void set_function (ftype p) { m_function = p; }
void call_function() {
if (m_function) m_function(size, value);
}
void call_ok_function() {
TheClass ok_class;
ok_class.set_function(foo);
ok_class.call_function();
}
void call_nasty_function() {
TheClass nasty_class;
// nasty_class.set_function(print);
// nasty_class.set_function(&TheClass::print);
nasty_class.call_function();
}
};
int TheClass::size = 0;
int main () {
TheClass one_class;
one_class.set_function(foo);
one_class.call_function();
one_class.call_ok_function();
one_class.call_nasty_function();
}
Как следует из примера, функция-член не может быть статической. Кроме того, я не могу переопределить исходную проблемную функцию для получения объекта.
Спасибо за любую помощь.
Редактировать
Я забыл упомянуть. Я попытался перейти на std::function, но моя исходная функция имеет более 10 аргументов (это подпрограмма Fortran).
Решение
Я внес изменения в std::function
и std::bind
, как было предложено, но не стал переделывать функцию с более чем 10 аргументами. Я решил создать промежуточную функцию. Следующий код иллюстрирует то, что я сделал, но с меньшим количеством переменных. Спасибо всем.
#include <iostream>
#include <boost/tr1/functional.hpp>
using namespace std;
class TheClass;
typedef tr1::function<void(int *, double *, double *, double *)> ftype;
// Suppose foo is from another file. Can't change the definition
void foo (int n, int m, double *A, double *x, double *b) {
// Performs matrix vector multiplication x = A*b, where
// A is m x n
}
void foo_wrapper (int DIM[], double *A, double *x, double *b) {
foo(DIM[0], DIM[1], A, x, b);
}
class TheClass {
private:
ftype m_function;
void my_function (int DIM[], double *A, double *x, double *b) {
// Change something before performing MV mult.
m_function(DIM, A, x, b);
}
public:
void set_function (ftype p) { m_function = p; }
void call_function() {
int DIM[2] = {2,2};
if (m_function) m_function(DIM, 0, 0, 0);
}
void call_nasty_function() {
TheClass nasty_class;
ftype f = tr1::bind(&TheClass::my_function, this, _1, _2, _3, _4);
nasty_class.set_function(f);
nasty_class.call_function();
}
};
int main () {
TheClass one_class;
one_class.set_function(foo_wrapper);
one_class.call_function();
one_class.call_nasty_function();
}
PS. Создание std::function
с более чем 10 переменными казалось возможным (скомпилировано, но я не тестировал) с помощью
#define BOOST_FUNCTION_NUM_ARGS 15
#include <boost/function/detail/maybe_include.hpp>
#undef BOOST_FUNCTION_NUM_ARGS
Но создать std::bind
для более чем 10 аргументов не так просто.