简体   繁体   中英

C++ stable_partition Compiler Error

I'm trying to extend an example I found in Koenig and Moo's "Accelerated C++." I've got the following code which attempts to split a vector into two partitions.

#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 get an error when I attempt to compile this file with 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

Obviously this is a toy example, but I've checked the function prototypes and I'm not sure where I'm going wrong here. Any suggestions?

You'll need to use mem_fun to turn the member function into an function object, then use bind1st to supply the this pointer.

I was never particularly successful getting this stuff to work on a regular basis (the standard library algorithms seem to be mainly designed for use with freestanding functions or hand-written predicate classes), but something like this should do the trick:

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

mem_fun gives you back a function object that takes two arguments, the first being the object to invoke mem_fun 's member function on, and the second being the single argument to the member function.

bind1st takes a function object that takes two arguments, and returns you a new one that takes one argument, which when invoked via operator() will call the original function object with the bind1st 's argument as its first argument and the supplied argument as the second.

The end result is that a new function object is created, that takes one argument, and that will call this->sameBaseReg , passing in the supplied argument.

The problem is that sameBaseReg is a member function of AnalyzeMemOps . You can't use it like an ordinary non-member function because it can only be called on an object.

If you have a modern compiler that supports C++0x, C++ TR1, or if you have Boost handy, you can use bind to bind the pointer to member function to the this object:

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

In the current C++ standard library, the <functional> library has std::mem_fun , std::bind1st , and other functions that can help with this, but they are an absolute beating to use effectively.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM