2017-04-04 46 views
4

下面是兩個std::lower_bound & std::upper_bound樣本示例中,注意比較拉姆達的簽名傳遞給他們 -不同的比較簽名:: LOWER_BOUND

const auto lower_x = std::lower_bound(
      points.begin(), points.end(), rec.min_corner.x, 

      [](const RankedPoint &rp, const double x) { return rp.point.x < x; }); 

const auto upper_x = std::upper_bound(
      points.begin(), points.end(), rec.max_corner.x, 

      [](const double x, const RankedPoint &rp) { return x < rp.point.x; }); 

什麼是可能的推理保持簽名完全相反?我沒有意識到這一點和gcc編譯(鐺沒有),當我用auto而不是具有錯誤簽名的確定類型。讓我失望了10分鐘。

+0

因爲比較函數的語義必須「小於'<'」。 – kennytm

+0

範圍庫將允許投影去除這個問題:-) – Jarod42

回答

3

lower_boundupper_bound的自定義比較版本是簡單使用<的概括。 lower_bound產生的第一個元素不小於value,因此發生的檢查是elem < value(或確實是!(elem < value))。 upper_bound產生的第一個元素大於而不是value,但我們不是寫elem > value(這需要operator>),我們只是將訂單翻轉爲value < elem。這保持了operator<的唯一要求,但是結果是,參數的順序是相反的。

這概括從elem < valuecomp(elem, value)value < elemcomp(value, elem)。最終,我們在設計時可以做出兩種選擇:我們可以在任何地方使用相同的比較器,但是對於某些算法,參數的順序是相反的。或者,我們可以使用不同的用於每種算法的比較器,具體取決於該特定算法的意義。使用相同的比較到處都有很多好處 - 你只需要使用相同的比較:

std::vector<int> vs = ...; 
std::sort(vs.begin(), vs.end(), std::greater<>{}); 
auto lo = std::lower_bound(vs.begin(), vs.end(), 5, std::greater<>{}); 
auto hi = std::upper_bound(vs.begin(), vs.end(), 5, std::greater<>{}); 

相同的比較無處不在,代碼看起來正確,做正確的事。如果我們翻轉upper_bound()傳遞給比較器的參數順序,我們必須通過std::less<>{}。這隻會......看起來不對。


你可能會喜歡Ranges TS,解決了這個問題,可調用的預測。

+0

寫你自己的投影是所有'template auto projected_order(F && f){return [f = std :: forward (f)](auto&lhs,auto&rhs) - > bool {return f(lhs) Yakk