2014-02-19 53 views
6

假設我有A類的成員函數int f() { return m_; },其中m_是數據成員。我有一個叫vecvector<A>,我想用std::max_elementvec中找到最大值爲m_的對象。我可以用一個lambda做到這一點:將多個參數綁定到C++中的成員函數

auto cmp = [] (A& x, A& y) { return x.f() < y.f(); }; 
A& max_elem = *std::max_element(vec.begin(), vec.end(), cmp); 

有一些bind(或類似)弄虛作假,讓我這樣做沒有拉姆達並沒有從頭開始定義自己的比較?請不要建議更好的方法來解決最大發現問題。這只是一個例子。一般的問題是如何包裝一個帶有多個參數的函數對象(例如,std::less<int>,我將在上面的示例中用作比較器),以便發送給它的參數通過其他函數(或成員函數)。

+0

既然你對你的決定哪個'的F()'應該是你比較基地隨意選擇的,我看不出有什麼希望這樣做*沒有*一些*類型的自定義比較器(無論是函子還是lambda,而我的錢在前者用於指向成員的便利)。或者......我完全不理解這個問題(它的2點半在這裏,現在真的應該在牀上)。 – WhozCraig

+0

查看['std :: bind'](http://en.cppreference.com/w/cpp/utility/functional/bind),['std :: placeholders :: _ 1'](http:// en .cppreference.com/w/cpp/utility/functional /佔位符)和相關。 – Angew

+0

當我說「沒有從頭開始定義我自己的比較器」時,我的意思是我想從'less <>'和其他構建塊(比如'bind')這樣的東西放在一起,最終會調用'f() '。我已經看過「綁定」和「佔位符」,但無法弄清楚如何處理這些問題。 – Ari

回答

11

是的,有:

using namespace std::placeholders; 
A& max = *std::max_element(begin(vec), end(vec) 
    , std::bind(
     &std::less<int>::operator() 
     , std::less<int>() 
     , std::bind(&A::f, _1) 
     , std::bind(&A::f, _2) 
    ) 
); 

Live example

但是,如果我看到這個在代碼審查,我會馬上說: 「把那醜陋爲lambda」。


感謝@n.m。對於poining出的代碼可以縮短一點:

using namespace std::placeholders; 
A& max = *std::max_element(begin(vec), end(vec) 
    , std::bind(
     std::less<int>() 
     , std::bind(&A::f, _1) 
     , std::bind(&A::f, _2) 
    ) 
); 

Live example

我仍然認爲一個lambda更具可讀性,雖然。請記住,您可以在max_element()的調用中直接使用lambda(不需要原始代碼中的變量cmp)。

+0

好的。這真是太棒了。 – WhozCraig

+2

'operator()'被稱爲'operator()'有一個原因:當你想調用它時,你不必命名它;)'std :: bind(std :: less (),std :: bind(&A :: f,_1),std :: bind(&A :: f,_2))'就夠了。 –

+0

有趣。這正是我的第一個想法,但我確信'_1'和'_2'不會通過(不知道所有這些是如何實現的),我甚至沒有嘗試過。讓我看看它是否有效。 – Ari

0

有幾種方法可以爲算法提供謂詞。下面你會看到一些如何做到這一點的例子。這裏的呼叫的總結std::max_element()

//here we're using an in-place lambda 
A& max_elem = *std::max_element(vec.begin(), vec.end(), [](A& x, A&y){ return x.f() < y.f(); }); 
// here we're binding to a non-static member function 
A& max_elem = *std::max_element(vec.begin(), vec.end(), std::bind(&A::compare, A(0), std::placeholders::_1, std::placeholders::_2)); 
// here we're binding to a non-member function 
A& max_elem = *std::max_element(vec.begin(), vec.end(), std::bind(gcompare, std::placeholders::_1, std::placeholders::_2)); 
// here we're using the non-member function without using bind 
A& max_elem = *std::max_element(vec.begin(), vec.end(), gcompare); 

我們也可以使用std::function

下面是完整的測試源代碼,以便您可以自己玩它:

class A 
{ 
    int m_ = 0; 
public: 
    A(int max) : m_(max) 
    { 

    } 
    A(const A& that) 
    { 
     m_ = that.m_; 
    } 
    A& operator=(const A& that) 
    { 
     m_ = that.m_; 
    } 
    int f() const 
    { 
     return m_; 
    } 
    bool compare(const A&x, const A&y) const 
    { 
     return x.m_ < y.m_; 
    } 
    static bool scompare(const A&x, const A&y) 
    { 
     return x.m_ < y.m_; 
    } 
}; 

static bool gcompare(const A&x, const A&y) 
{ 
    return x.f() < y.f(); 
} 

int main() 
{ 
    std::vector<A> vec; 
    vec.emplace_back(5); 
    vec.emplace_back(7); 
    vec.emplace_back(4); 
    vec.emplace_back(9); 
    vec.emplace_back(12); 
    vec.emplace_back(1); 


    A& max_elem = *std::max_element(vec.begin(), vec.end(), [](A& x, A&y){ return x.f() < y.f(); }); 
    A& max_elem = *std::max_element(vec.begin(), vec.end(), std::bind(&A::compare, A(0), std::placeholders::_1, std::placeholders::_2)); 
    A& max_elem = *std::max_element(vec.begin(), vec.end(), std::bind(gcompare, std::placeholders::_1, std::placeholders::_2)); 
    A& max_elem = *std::max_element(vec.begin(), vec.end(), gcompare); 

}