2010-11-25 213 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,传入提供的参数。