2015-09-23 13 views
8

Tôi có một foostd::vector<int>. Nó đại diện cho các giá trị "cạnh" cho một tập các phạm vi. Ví dụ: nếu foo là {1, 3, 5, 7, 11} thì phạm vi là 1-3, 3-5, 5-7, 7-11. Đáng kể đối với tôi, điều này tương đương với 4 giai đoạn. Lưu ý rằng mỗi khoảng thời gian bao gồm số đầu tiên trong một phạm vi và không phải là số cuối cùng. Vì vậy, trong ví dụ của tôi, 8 xuất hiện trong khoảng thời gian thứ 3 (không dựa trên). 7 cũng xuất hiện trong giai đoạn thứ 3. 11 và ở trên không xuất hiện ở bất cứ đâu. 2 xuất hiện trong khoảng thời gian thứ 0.Một sự thay thế cho std :: bind2nd

Cho một bar mà là một int, tôi sử dụng

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

để cho tôi thời gian đó nên chứa bar.

Vấn đề của tôi: std::bind2nd không được chấp nhận vì vậy tôi nên tái cấu trúc lại. Câu lệnh tương đương sử dụng các hàm được cập nhật là gì? std::bind không "rơi vào" theo cách hiển nhiên.

+3

BTW, 'std :: distance (foo.begin(), std :: lower_bound (foo.begin(), foo.end(), bar)) - 1;' có vẻ phù hợp hơn ở đây. – Jarod42

Trả lời

9

Trong C++ 11, bạn có thể sử dụng std::bind; nó chỉ không rõ ràng cách sử dụng nó:

#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; 

Điều quan trọng là việc sử dụng đối số giữ chỗ, được khai báo trong không gian tên std::placeholders. std::bind trả về một đối tượng hàm nhận một số tham số khi nó được gọi. Trình giữ chỗ được sử dụng bên trong cuộc gọi đến std::bind cho biết cách các đối số được cung cấp khi đối tượng kết quả được gọi là ánh xạ tới danh sách đối số đến hàm có thể gọi mà bạn đang ràng buộc. Vì vậy, ví dụ:

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 phiên bản sẽ là:

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

nhưng tôi nghĩ rằng, đó là khuyến khích hơn để sử dụng lambdas, như trong:

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

Nó cũng được khuyến khích sử dụng chức năng quá tải begin/end thay vì gọi phương thức. do đó nó sẽ như thế nào:

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

'placeholder :: _ 1' là gì? –

+0

Bạn có thể là một thiên thần và đặt toàn bộ mọi thứ lại với nhau? ;-) –

+0

@ P45Imminent theo nghĩa đen _placeholders_; xem [ở đây] (http://www.cplusplus.com/reference/functional/placeholders/?kw=placeholders) –

8

gì về việc đi thẳng từ thời kỳ đồ đá (bind2nd) để thời đại đồ sắt với C++ 14 lambda chung, bỏ qua thời kỳ đồ đồng (bind)?

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

Và nếu đầu vào được sắp xếp

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

Lambdas đọc dễ dàng hơn và cũng dễ dàng hơn để nội tuyến hơn std::bind expresions. Xem ví dụ Lavevej's CppCon 2015 nói chuyện.

+1

Tôi đồng ý rằng đây có lẽ là giải pháp dễ đọc nhất, nhưng các thẻ của câu hỏi chỉ bao gồm C++ 11. –

+0

@ JasonR triết lý của tôi là thể hiện cách tôi sẽ viết mã, trừ khi họ tuyên bố rằng họ thực sự không thể sử dụng C++ 14, và thậm chí sau đó tôi sẽ hiển thị nếu tiền tiết kiệm đủ lớn :) Hỏi & Đáp không chỉ cho OP, nhưng cho công chúng nói chung. Nhưng tôi đã upvoted câu trả lời 'bind' của bạn :) – TemplateRex

+0

Đủ công bằng; điều đó có ý nghĩa. +1. –

Các vấn đề liên quan