2015-09-23 16 views
8

var, std::vector<int>. Bir dizi aralık için "kenar" değerlerini temsil eder. Örneğin, foo, 0, 1, 3, 5, 7, 11} ise, aralıklar 1-3, 3-5, 5-7, 7-11'dir. Benim için önemli olan, bu 4 döneme eşittir. Her dönemin, bir aralıktaki ilk sayıyı ve sonuncuyu içermediğini unutmayın. Yani benim örneğimde, 8 (sıfır tabanlı) dönemde 8 görüntülenir. 7 de 3. dönemde belirir. 11 ve üstü hiçbir yerde görünmüyor. 2, 0 döneminde görünür.std :: bind2nd için bir yedek

bir int bir bar göz önüne alındığında, bana bar içermelidir süresi tanıyabilir

std::find_if(
    foo.begin(), 
    foo.end(), 
    std::bind2nd(std::greater<int>(), bar) 
) - foo().begin() - 1; 

kullanın.

Sorunum: std::bind2nd kullanımdan kaldırıldı, bu nedenle yeniden düzenleme yapmam gerekiyor. Güncellenen işlevleri kullanan eşdeğer deyim nedir? std::bind bariz şekilde "düşmez".

+3

BTW, 'std :: distance (foo.begin(), std :: lower_bound (foo.begin(), foo.end(), bar)) - 1;' burada daha uygun görünüyor. – Jarod42

cevap

9

C++ 11'de std::bind; Sadece nasıl kullanılacağını olarak açık değildir:

#include <functional> 
using namespace std::placeholders; 
std::find_if(
    foo.begin(), 
    foo.end(), 
    // create a unary function object that invokes greater<int>::operator() 
    // with the single parameter passed as the first argument and `bar` 
    // passed as the second argument 
    std::bind(std::greater<int>(), _1, bar) 
) - foo().begin() - 1; 

anahtar std::placeholders ad bildirilen tutucu argüman, kullanılmasıdır. std::bind, çağrıldığında bazı parametreler alan bir işlev nesnesi döndürür. std::bind aramasındaki yer tutucuları, elde edilen nesne çağrıldığında verilen argümanların argüman listesine bağlandığınız satıra nasıl eşlendiğini gösterir. Dolayısıyla, örneğin:

auto op1 = std::bind(std::greater<int>(), _1, bar); 
op1(5); // equivalent to std::greater<int>()(5, bar) 

auto op2 = std::bind(std::greater<int>(), bar, _1); 
op2(5); // equivalent to std::greater<int>()(bar, 5) 

auto op3 = std::bind(std::greater<int>(), _2, _1); 
op3(5, bar); // equivalent to std::greater<int>()(bar, 5) 

auto op4 = std::bind(std::greater<int>(), _1, _2); 
op4(5, bar); // equivalent to std::greater<int>()(5, bar) 
5

bind versiyonu olacaktır: Aynı zamanda teşvik edilmektedir

[bar](const int a){return bar < a;} 

:

bind(std::greater<int>(), placeholders::_1, bar) 

ama sanırım gibi lambdas kullanmak daha çok teşvik olduğunu Yöntem çağrıları yerine aşırı işlevler begin/end kullanmak için. Ne Tunç (bind) atlayarak bir C++ 14 jenerik lambda'da Demir Çağı'na (bind2nd) Taş Devrinden düz gitmeyi

find_if(begin(foo), end(foo), [bar](const int a){return bar < a;}) 
+0

Yer tutucuları :: _ 1 'nedir? –

+0

Bir melek olabilir ve her şeyi bir araya getirebilir misiniz? ;-) –

+0

@ P45Imincent tam anlamıyla _placeholders_; bkz. [here] (http://www.cplusplus.com/reference/functional/placeholders/?kw=placeholders) –

8

: bu yüzden gibi olurdu? giriş

std::lower_bound(foo.begin(), foo.end(), bar); 

sıralansaydı
std::find_if(foo.begin(), foo.end(), [&](auto const& elem) { 
    return elem > bar; 
}); 

Ve

Lambda'lar çok daha kolay okunur ve ayrıca std::bind expresions daha satır içi daha kolaydır. Bakınız örn. Lavevej's CppCon 2015 konuşun.

+1

Bunun muhtemelen en kolay okunan çözüm olduğunu kabul ediyorum, ancak sorunun etiketleri sadece C++ 11'i içeriyordu. –

+0

@JasonR Benim felsefem, C++ 14'ü gerçekten kullanamadıklarını iddia etmedikçe ve hatta tasarruflar yeterince büyükse bunu göstermeyi beklemediğim sürece nasıl kodlayacağımı göstermektir :) Soru & Cevap sadece OP için, ama halk için geniş. Ama ben 'bind' cevabını yedim :) – TemplateRex

+0

Yeterince adil; bu mantıklı. +1. –