2008-12-16 34 views
10

Có ai biết nếu có một đối tượng chức năng tiêu chuẩn de-facto (tức là, TR1 hoặc Boost) C++ để truy cập các phần tử của một cặp std ::? Hai lần trong 24 giờ qua tôi đã ước mình có một cái gì đó giống như hàm keys cho các băm Perl. Ví dụ, nó sẽ là tốt đẹp để chạy std :: transform trên một đối tượng std :: map và đổ tất cả các khóa (hoặc các giá trị) vào một container khác. Tôi chắc chắn có thể viết một đối tượng chức năng như vậy nhưng tôi muốn sử dụng lại thứ gì đó có rất nhiều nhãn cầu trên đó.Có một đối tượng hàm C++ tiêu chuẩn để tách rời một cặp :: std không?

Trả lời

17

boost::bind là những gì bạn tìm kiếm.

boost::bind(&std::pair::second, _1); // returns the value of a pair 

Ví dụ:

typedef std::map<std::string, int> map_type; 

std::vector<int> values; // will contain all values 
map_type map; 
std::transform(map.begin(), 
       map.end(), 
       std::back_inserter(values), 
       boost::bind(&map_type::value_type::second, _1)); 
4

Từ cách bạn đặt câu hỏi của mình, tôi không chắc đây có phải là câu trả lời đúng hay không, nhưng hãy thử boost::tie (một phần của thư viện Boost :: tuple). Nó cũng hoạt động trên std::pair.

3

boost::bind thường được sử dụng để thích ứng container std :: bản đồ để sử dụng với thuật toán. Here là ví dụ:

void print_string(const std::string& s) { 
    std::cout << s << '\n'; 
} 


std::map<int,std::string> my_map; 
my_map[0]="Boost"; 
my_map[1]="Bind"; 


std::for_each(my_map.begin(), my_map.end(), 
       boost::bind(&print_string, boost::bind(
       &std::map<int,std::string>::value_type::second,_1))); 
1

Điều gì về việc sử dụng kết hợp các vùng chứa khác nhau.

Ví dụ khi tôi muốn phân vùng một vector vào mục chứa trong một bản đồ bổ sung và các mặt hàng mà trong đó không có trong bản đồ bổ sung tôi đã sử dụng như sau:

typedef int DWORD; 
typedef std::pair<std::string, bool> user_info; 
typedef std::map<DWORD, user_info> USER_MAP; 
typedef std::vector<DWORD> VEC_STAFF; 

VEC_STAFF::iterator it = std::partition(Staff.begin(), Staff.end(), (bind(&USER_MAP::find, m_Users, _1) != m_Users.end())); 

Bây giờ tôi có một vấn đề thứ hai - trong hoạt động của ứng dụng bool trạng thái của user_info có thể thay đổi, và sau này tôi muốn phân vùng lại vectơ với các mục có bool trạng thái đúng hơn là chỉ được chứa trong bản đồ bổ sung.

Tuy nhiên, dường như tôi gặp sự cố khi truy cập mục thứ hai của cặp lồng nhau.

Tôi đã thử những điều sau nhưng tôi dường như không thể truy cập cặp lồng nhau!

CActiveUsers::VEC_STAFF::const_iterator itCurEnd = partition(Staff.begin(), Staff.end(), bind(&USER_MAP::value_type::second::second, bind(&USER_MAP::find, &m_Users, _1)) == true); 
1

Hãy xem xét tăng :: bộ điều hợp. Có các bộ điều hợp được xác định trước để lặp qua các khóa hoặc giá trị bản đồ mà không cần sao chép chúng vào một vùng chứa trung gian.

0

Một tùy chọn không được đề xuất là std::tr1::get. Xem phần 6.1.2 và 6.1.4 của n1745.

std::pair< std::string, int > p("foo", 1729); 

int hr = std::tr1::get<1>(p); 

Chắc chắn không phải là dễ dàng để sử dụng như bind trong trường hợp map khai thác mà bạn đề cập nhưng vẫn đáng được biết đến. Điều chỉnh mã của Johannes:

typedef std::map<std::string, int> map_type; 

std::vector<int> values; // will contain all values 
map_type map; 

// std::tr1::get is overloaded so we need to help the compiler choose 
const map_type::value_type::second_type & (*get)(const map_type::value_type &) = 
    &std::tr1::get< 1, map_type::value_type::first_type, map_type::value_type::second_type >; 

std::transform(map.begin(), 
       map.end(), 
       std::back_inserter(values), 
       get); 
Các vấn đề liên quan