4

概要

最適化問題を格納し、その問題に対してソルバーを実行するクラスがあります。ソルバーが失敗した場合は、サブ問題を検討し、同じソルバー(およびクラス)を使用して解決したいと思います。

序章

最適化問題は、本質的に多くの(数学的な)関数です。問題のある関数はクラスの外部で定義されていますが、サブの問題の関数はクラスの内部で定義されているため、タイプは異なります(例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::functionstd::bind10個を超える引数を持つ関数の再設計は行いませんでした。中間関数を作成することにしました。次のコードは、私が行ったことを示していますが、変数は少なくなっています。ありがとうございます。

#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::function10を超える変数を使用してを作成することは可能であるように見えました(コンパイルされましたが、テストしませんでした)。

#define BOOST_FUNCTION_NUM_ARGS 15
#include <boost/function/detail/maybe_include.hpp>
#undef BOOST_FUNCTION_NUM_ARGS

しかしstd::bind、10を超える引数のを作成するのは簡単ではないようです。

4

1 に答える 1

3

std::function、、std::bindおよびラムダはあなたが探しているものです。要するに、関数ポインタは非常に悪いものであり、火の中に燃やされるべきです。長い間、std::function正しいシグニチャで呼び出すことができる任意の関数オブジェクトを格納できます。std::bindまたはラムダを使用して、メンバー関数をすばやく簡単に呼び出す関数オブジェクトを生成できます。

編集:次にstd::function、10個を超える引数をサポートする独自の同等物をロールする必要があります。

于 2012-10-30T19:53:29.693 に答える