0

C++ クラスがあり、そのフィールドの 1 つはオブジェクトの std::set です。独自の比較関数を作成するか、ユーザーに指定させたい。C++11 では、汎用関数型を処理する新しい方法 std::function があります。関数ポインター、メンバー関数ポインター、ラムダ関数などで動作します。

簡単な実験プログラムを作成しようとしましたが、C++11 Wikipedia の記事が示唆していることを実行しても、常にクラッシュし続けます。std::function と std::ref がどのように使用されることになっているのかわからないだけかもしれません。

とにかく、ポイントは、単純なラムダ関数から std::function を作成し、それをクラス メンバーにしたときに、クラスの sizeof が 22 増加したことです。グローバル関数へのポインターから std::function を作成したとき、この std::function の sizeof は 32 でした。したがって、サイズは大きいです。同じ比較関数を使用するオブジェクトが多数あるので、それらすべてで 1 つの関数を使用することを好みます。

2つの考えがあります、あなたの考えを教えてください。1 つのアイデアは、std::ref を使用して関数への参照を格納することです。このようにして、1 つの関数を定義でき、多くのオブジェクトがそれを使用して std::set 要素を比較します。2 番目のアイデア: そのように機能しない場合、または結果の関数オブジェクトがとにかく大きすぎる場合は、shared_ptr を使用できます。

あなたは疑問に思うかもしれません: 静的な std::function メンバーが 1 つないのはなぜですか? 答え: すべてのオブジェクトが同じ比較関数を使用するためです。たとえば、ある比較関数を使用して 400 個、別の比較関数を使用して 600 個のオブジェクトを 1000 個持つことができるようにしたいと考えています。

例:

class MyClass
{
public:
private:
     std::function<bool (int, int)> compare;
     std::set<int> set;
};

std::set で std::function を使用し、多くの MyClass オブジェクトで同じ関数を使用するにはどうすればよいでしょうか。

実行時に比較関数を変更できるようにして、ユーザーがセット内のオブジェクト (GUI で表示される) の順序を選択できるようにしたいと考えています。

4

2 に答える 2

2

コンストラクタ初期化子リストで比較関数を使用するようにセットに指示します。

class MyClass
{
public:
    template<typename Fc>
    MyClass(Fc compare_func)
        : compare(compare_func),  // Initialize the comparison function
          set(compare)            // Tell the set to use out function for comparison
        {}
};
于 2013-02-15T11:36:53.000 に答える
2

共有所有権を表す標準的な方法は、 を使用することstd::shared_ptrです。これによりオーバーヘッドが少し増えstd::function、ヒープに を割り当てる必要がありますが、ashared_ptrは a よりも小さく、std::functionその有効期間を正しく管理するため、オブジェクトがまだ関数オブジェクトを使用している間は、生きたままになり、次の場合に自動的に破棄されます。不要になりました。

あなたが示唆するようreference_wrapperに、共有関数を参照するaは、呼び出し可能な型をラップすると呼び出し可能setであるため、 の比較オブジェクトとして使用できます。reference_wrapper

class MyClass
{
     typedef std::function<bool (int, int)> func_type;
public:
     MyClass(std::shared_ptr<func_type> const& f)
     : compare(f), set( std::ref(*f) )
     { }
private:
     std::shared_ptr<func_type> compare;
     std::set<int, std::reference_wrapper<func_type>> set;
};

Areference_wrapperを (参照のように) null にすることはできないためstd::set、有効なreference_wrapperオブジェクトを使用して を構築する必要があります。

のは への非所有ポインターを保持しstd::reference_wrapperているだけなので、の更新と同時にセットの比較オブジェクトを更新するように注意する必要があります。セットにダングリングポインターを残します。それは次のように行うことができます:std::setstd::functionshared_ptrshared_ptr

void MyClass::replace_cmp(std::shared_ptr<func_type> const& f)
{
  set = std::set<int, std::reference_wrapper<func_type>>( std::ref(*f) );
  compare = f;
}
于 2013-02-15T11:27:02.077 に答える