2011-01-25 34 views

Trả lời

6

các map iterator sẽ cung cấp cho bạn một pair nơi first là chìa khóa intsecond là giá trị của bản đồ pair, vì vậy nếu bạn h quảng cáo một trình lặp số it, bạn muốn tối thiểu tất cả các giá trị it->second.first. Hàm min_element mong đợi một hàm so sánh cho đối số thứ ba của nó, vì vậy bạn cần xây dựng hàm so sánh dự án second.first của hai đối số của nó.

Chúng tôi sẽ bắt đầu với một số typedefs để làm cho mã dễ đọc hơn:

typedef std::pair<short, float> val_type; 
typedef std::map<int, val_type> map_type; 
map_type m; 

Chúng ta sẽ sử dụng Boost.Lambda cho các nhà khai thác quá tải của nó, cho phép chúng ta sử dụng operator<. Boost.Bind có thể ràng buộc các biến thành viên cũng như các hàm thành viên, vì vậy chúng ta cũng sẽ tận dụng lợi thế của nó.

#include <boost/bind.hpp> 
#include <boost/lambda/lambda.hpp> 
using boost::bind; 

// Comparison is (_1.second.first < _2.second.first) 
std::cout << 
    std::min_element(m.begin(), m.end(), 
    bind(&val_type::first, bind(&map_type::iterator::value_type::second, _1)) 
    < 
    bind(&val_type::first, bind(&map_type::iterator::value_type::second, _2)) 
)->second.first; 

Điều đó cũng sẽ hoạt động với boost::lambda::bind.

2

bind không thể tự làm điều này, bởi vì firstsecond được hiển thị dưới dạng trường, chứ không phải là phương pháp (vì vậy bạn không thể lấy một thứ gì đó như mem_fun).

Bạn có thể làm điều này bằng functor của riêng bạn dĩ nhiên mặc dù:

template <typename F, typename S> 
struct select_first : std::binary_function<std::pair<F, S>&, F&> 
{ 
    F& operator()(std::pair<F, S>& toConvert) 
    { 
     return toConvert.first; 
    } 
}; 
+1

Còn được gọi là 'select1st' trong một số thư viện C++. – ephemient

+0

@ephemient: Đúng - không biết rằng nó đã được bao gồm trong STL của SGI. Trong trường hợp đó tôi sẽ khuyên bạn nên để lại tên theo cách này bởi vì SGI hỗ trợ bất kỳ giao diện giống như cặp nào, trong khi điều này chỉ hoạt động với std :: pair. –

5
min_element(map.begin(), map.end(), 
      compose2(less<short>(), 
        compose1(select1st<pair<short, float> >(), 
           select2nd<map<int, pair<short, float> 
              >::value_type>()), 
        compose1(select1st<pair<short, float> >(), 
           select2nd<map<int, pair<short, float> 
              >::value_type>())) 
      ).second.first; 

(Tất nhiên, ai đó sẽ phàn nàn rằng đây là một sự lạm dụng của STL và rằng đây là những phần mở rộng không có trong C++ tiêu chuẩn ...)

+0

Vâng, tôi sẽ khiếu nại về các phần mở rộng không chuẩn, nhưng theo như "lạm dụng STL" đi tôi nghĩ rằng nó hoàn toàn tốt :) 1. May mắn là các bit không chuẩn sẽ dễ viết. –

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