2010-11-25 18 views
2

私はケーニッヒで見つかった例を拡張しようとしていると武の「加速C++。」私はベクトルを2つのパーティションに分割しようとする次のコードを持っています。C++コンパイラstable_partitionエラー

#include <algorithm> 
#include <vector> 
#include <iostream> 

using namespace std; 

struct MyClass { 
    int* MyInt; 
    MyClass() : MyInt(NULL) {} 
}; 

struct AnalyzeMemOps { 
    vector<MyClass> AllMyClassRecords; // Where I keep the MyClass instances 
    bool sameBaseReg(MyClass m); 
    vector<MyClass> splitBySameBase(vector<MyClass>& main); 
    AnalyzeMemOps() {} 
}; 

// Predicate function for stable_partition 
bool AnalyzeMemOps::sameBaseReg(MyClass m) { 
    return true; 
} 

vector<MyClass> AnalyzeMemOps::splitBySameBase(vector<MyClass>& main) { 
    vector<MyClass>::iterator it = 
     stable_partition(main.begin(), main.end(), sameBaseReg); // Error is here 
    vector<MyClass> sameBases(it, main.end()); 
    main.erase(it, main.end()); 

    // Print results 
    cout << "Split By Same Base: Returning SameBase Instrs\n"; 
    for (vector<MyClass>::iterator i = sameBases.begin(); i != sameBases.end(); ++i) { 
     cout << " " << i->MyInt << "\n"; 
    } 

    return sameBases; 
} 

int main() { 
    AnalyzeMemOps AMCR; 

    MyClass m; 
    AMCR.AllMyClassRecords.push_back(m); 
    AMCR.AllMyClassRecords.push_back(m); 
    AMCR.AllMyClassRecords.push_back(m); 

    vector<MyClass> t = AMCR.splitBySameBase(AMCR.AllMyClassRecords); 
} 

IがG ++でこのファイルをコンパイルしようとしたとき、私はエラーを取得:

Tile.cpp: In member function \u2018std::vector<MyClass, std::allocator<MyClass> > AnalyzeMemOps::splitBySameBase(std::vector<MyClass, std::allocator<MyClass> >&)\u2019: 
Tile.cpp:26: error: no matching function for call to \u2018stable_partition(__gnu_cxx::__normal_iterator<MyClass*, std::vector<MyClass, std::allocator<MyClass> > >, __gnu_cxx::__normal_iterator<MyClass*, std::vector<MyClass, std::allocator<MyClass> > >, <unresolved overloaded function type>)\u2019 
/usr/include/c++/4.4/bits/stl_algo.h:1864: note: candidates are: _BIter std::stable_partition(_BIter, _BIter, _Predicate) [with _BIter = __gnu_cxx::__normal_iterator<MyClass*, std::vector<MyClass, std::allocator<MyClass> > >, _Predicate = bool (AnalyzeMemOps::*)(MyClass)] 
make: *** [a.out] Error 1 

は明らかにこれはおもちゃの例ですが、私は関数プロトタイプをチェックしましたし、私がどこか分かりません私はここで間違っています。助言がありますか?

答えて

3

問題はsameBaseRegAnalyzeMemOpsのメンバ関数であるということです。オブジェクトに対してのみ呼び出すことができるので、通常の非メンバー関数のように使用することはできません。

あなたがC++ 0xの、C++ TR1をサポートして近代的なコンパイラを持っている場合は、便利なブーストがある場合、または、あなたがthisオブジェクトにメンバ関数へのポインタをバインドするbindを使用することができます。

std::bind(&AnalyzeMemOps::sameBaseReg, this, std::placeholders::_1) 

現在のC++標準ライブラリでは、<functional>ライブラリはstd::mem_funstd::bind1st、これを支援することができ、他の機能を持っていますが、彼らは効果的に使用するための絶対的な打撃です。

+0

どのように「悪いフォーム」それはsplitBySameBaseメンバ関数は、sameBaseRegの非メンバ関数のバージョンを呼び出して作成するのでしょうか?私は、sameBaseRegが同じ名前空間にある場合、それが正常に動作することを発見しました。 – Zeke

+1

@ Zeke:メンバー関数である必要がない場合は、間違いなくメンバ関数以外の関数にする必要があります。クラスのprivateまたはprotectedメンバ変数にアクセスする必要がない場合は、非メンバ関数である必要があります。 –

+0

そのようにすると、splitBySameBase関数全体がAnalyzeMemOpクラスにある必要はありません。私は組織の目的のためにクラス内のすべての機能を持っていましたが、彼らはメンバー機能である必要はないと思います!説明ありがとう。 – Zeke

3

mem_funを使用してメンバー関数を関数オブジェクトに変換し、次にbind1stを使用してthisポインタを指定する必要があります。

このようなことを定期的に行うことは決して成功しませんでした(標準ライブラリアルゴリズムは主にフリースタンディング関数や手書きの述語クラスで使用するように設計されています)が、

vector<MyClass>::iterator it = 
    stable_partition(main.begin(), 
        main.end(), 
        bind1st(mem_fun(&AnalyzeMemOps::sameBaseReg), 
          this)); 

mem_fun

は、最初は上 mem_funのメンバ関数を呼び出すためのオブジェクトであること、第二は、メンバ関数への単一の引数であること、背中二つの引数を取る関数オブジェクトをあなたに与えます。

bind1stは2つの引数を取る関数オブジェクトを取り、あなたはoperator()経由で呼び出された一つの引数を取る新しいものは、その最初の引数と供給の引数としてbind1stの引数を指定して、元の関数オブジェクトを呼び出します返します第2のものとして。

最終結果は一つの引数を取ること、新しい関数オブジェクトが作成されていることであり、それは与えられた引数に渡して、this->sameBaseRegを呼び出します。

関連する問題