2012-05-19 25 views
0

請原諒我,如果這之前已經問過,我只是無法找到一個合適的解決方案。什麼是最簡潔的方法來比較成員函數調用的結果

我經常發現自己創建一個類的成員函數函子像下面這樣使用find_if或的remove_if之後

class by_id{ 
    public: 
    by_id(int id):mId(id) {} 

    template <class T> 
    bool operator()(T const& rX) const { return rX.getId() == mId; } 

    template <class T> 
    bool operator()(T* const pX) const { return (*this)(*pX); } 

    private: 
    int mId; 
}; 

雖然這工作得很好它含有大量的樣板和手段來定義一個類我想用來比較每個成員函數。

我知道C++ 11中的lambdas,但由於交叉編譯器的限制,我無法切換到新的標準。

我發現的最接近的相關問題是stl remove_if with class member function result,但給定的解決方案意味着添加額外的成員函數進行比較,這很醜陋。

使用標準STL還是沒有更簡單的方法,或者可以使用更通用的方式編寫這樣的函數,或者使用bind來完全跳過它們?

像通用仿函數一樣會做,但我缺乏寫它的技巧。 只是爲了清楚我的想法:

template<typename FP,typename COMP> 
    class by_id{ 
     public: 
     by_id(COMP id):mId(id) {} 

     template <class T> 
     bool operator()(T const& rX) const { return rX.FP() == mId; } 
     //of course this does not work 

     template <class T> 
     bool operator()(T* const pX) const { return (*this)(*pX); } 

     private: 
     COMP mId; 
    }; 

回答

2

如果你知道T提前(在創建by_id的對象,你就可以說的by_id和模板參數傳遞一個指針成員函數爲了構造是這樣的:

template<typename T, typename COMP> 
class by_id 
{ 
public: 
    typedef COMP (T::*MemFunc)(); 
    by_id(COMP id, MemFunc mf) : mId(id), mmf(mf) {} 

    bool operator()(T const& rX) const { return rX.*mmf() == mId; } 

private: 
    COMP mId; 
    MemFunc mmf; 
}; 
+0

再次感謝您的寶貴意見代替boost::bind。那正是我所期待的。爲什麼這樣的事情不是某個圖書館的一部分,它似乎非常方便。 – Martin

1

您可以在成員函數指針傳遞到比較器,以指示比較哪個值

使用make_comparer。功能,以避免不必指定在使用點類型參數(類似於std::make_pair

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

template<typename T, typename R> 
class comparer 
{ 
public: 
    typedef R (T::*accessor_type)() const; 
    typedef R value_type; 
    comparer (accessor_type accessor, value_type value) : 
     accessor_ (accessor), value_ (value) { } 

    accessor_type accessor_; 
    value_type value_; 

    bool operator() (T const& rX) const { 
     return (rX.*accessor_)() == value_; 
    } 
    bool operator() (const T* pX) const { 
     return (*this) (*pX); 
    } 
}; 

template <typename T, typename R> 
comparer<T, R> make_comparer (R (T::*accessor)() const, R value) 
{ 
    return comparer<T, R> (accessor, value); 
} 

class Foo 
{ 
public: 
    explicit Foo (int id, int rank) : id_ (id), rank_ (rank) { } 
private: 
    int id_, rank_; 

public: 
    int id() const { 
     return id_; 
    } 
    int rank() const { 
     return rank_; 
    } 

}; 

std::vector<Foo> foos; 
typedef std::vector<Foo>::const_iterator FooIT; 

void print (FooIT it) 
{ 
    if (it == foos.end()) 
     std::cout << "no match" << std::endl; 
    else 
     std::cout << "matches id: " << it -> id() << " rank: " << it -> rank() << std::endl; 
} 

main() 
{ 

    foos.push_back (Foo (1, 3)); 
    foos.push_back (Foo (2, 2)); 
    foos.push_back (Foo (3, 1)); 

    std::cout << "compare id == 2 "; 
    print (std::find_if (foos.begin(), foos.end(), make_comparer (&Foo::id, 2))); 

    std::cout << "compare id == 3 "; 
    print (std::find_if (foos.begin(), foos.end(), make_comparer (&Foo::id, 3))); 

    std::cout << "compare rank == 3 "; 
    print (std::find_if (foos.begin(), foos.end(), make_comparer (&Foo::rank, 3))); 
} 
1
using namespace boost; 
std::find_if(first, last, bind(std::equal<int>(), bind(&Foo::getId, _1), id)); 

這創建嵌套bind表達式,並調用它的取值範圍爲[first,last),其中要求該綁定表達式中的每個元件一個元件Foo i等效於調用:

std::equal<int>()(i.getId(), id) 

即它測試如果i.getId()等於id

在C++ 11,你可以用std::bind

using namespace std::placeholders; 
std::find_if(first, last, std::bind(std::equal<int>(), std::bind(&Foo::getId, _1), id)); 
相關問題