2010-11-25 166 views
2

我想擴展我在Koenig和Moo的「加速C++」中找到的示例。我有下面的代碼試圖將一個矢量分成兩個分區。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); 
} 

我得到一個錯誤,當我嘗試編譯該文件使用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現代化的編譯器,或者如果你有升壓方便,你可以使用bind的成員函數指針綁定到this對象:

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

在當前的C++標準庫中,<functional>庫有std::mem_fun,std::bind1st和其他可以幫助解決這個問題的函數,但是它們是絕對有效使用的函數。

+0

如何使splitBySameBase成員函數調用sameBaseReg的非成員函數版本的「不良形式」?我剛剛發現,如果sameBaseReg在相同的命名空間中,它工作正常。 – Zeke 2010-11-25 01:24:05

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需要一個函數對象有兩個參數,並返回一個新的,有一個參數,當其通過operator()調用將調用與bind1st的參數作爲第一個參數,提供的參數原來的函數對象作爲第二。

最終的結果是創建了一個新的函數對象,它接受一個參數,並且將調用this->sameBaseReg,傳入提供的參數。