Указатель на функцию-член и не-член

У меня есть класс, который хранит проблему оптимизации и запускает решатель этой проблемы.
Если решатель терпит неудачу, я хочу рассмотреть подзадачу и решить, используя тот же решатель (и класс).

Задача оптимизации — это существенно много (математических) функций. Проблемные функции определены вне класса, но подзадачные функции определены внутри класса, поэтому они имеют разные типы (например, 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 аргументов (это подпрограмма на Фортране).

Я сделал изменения в 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 аргументов не все так просто.

4

Решение

std::function, std::bindи лямбды-это то, что вы ищете. Короче говоря, указатели функций — очень плохие вещи, и их следует сжигать в огне. Долго std::function может хранить любой объект функции, который может быть вызван с правильной подписью, и вы можете использовать std::bind или лямбда для генерации объекта функции, который вызывает вашу функцию-член быстро и легко.

Изменить: Тогда вам просто нужно накатить свой std::function эквивалент, который поддерживает более 10 аргументов.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]