2008-11-23 26 views
9

Tôi có một vùng chứa đầy các cặp. Tôi muốn lặp lại trong nó bằng cách sử dụng các thuật toán chung STL (trong trường hợp của tôi nó sẽ là inner_product, nhưng xem xét nó như là một vấn đề chung chung). Thuật toán tôi đang sử dụng dự kiến ​​vòng lặp đầu tiên và cuối cùng. Tôi có thể cung cấp vòng lặp đặc biệt đầu tiên và cuối cùng sẽ lặp lại không phải trên các cặp nhưng trên phần tử đầu tiên của mỗi cặp?Cung cấp một trình lặp cho phần tử đầu tiên của một cặp chứa

Tôi biết tôi có thể làm điều đó theo cách thủ công, cung cấp đối tượng hàm được tạo bằng tay sẽ là trình bao bọc xung quanh bộ lặp container chuẩn, đưa nó đến thành viên đầu tiên của cặp có ý định của cặp đó, nhưng tôi nghĩ có cũng là một lớp lót thông minh để làm điều đó cho tôi. No se như thê nao?

+0

bạn có nghĩa là ví dụ bạn có map.begin() và bạn muốn lặp qua các giá trị của nó (. Giây)? –

+0

Vâng, đó là một trường hợp khác của cùng một vấn đề cơ bản. –

+0

được cho phép tăng cường? :) –

Trả lời

11

Tôi đã xem xét và tìm thấy boost::transform_iterator. Tôi đã đưa ra mã này. Ngạc nhiên khi hoạt động tốt:

#include <map> 
#include <algorithm> 
#include <iostream> 
#include <string> 
#include <iterator> 
#include <boost/iterator/transform_iterator.hpp> 
#include <boost/bind.hpp> 
#include <boost/function.hpp> 

int main() { 
    typedef std::map<std::string, int>::value_type value_type; 
    std::map<std::string, int> a; 
    a["one"] = 1; 
    a["two"] = 2; 

    // returns the second element 
    boost::function<int(value_type&)> f = boost::bind(&value_type::second, _1); 
    std::copy(boost::make_transform_iterator(a.begin(), f), 
       boost::make_transform_iterator(a.end(), f), 
       std::ostream_iterator<int>(std::cout, " ")); 

} 

Đang in "1 2 " cho đầu ra tiêu chuẩn.

+0

Nó gần như là một "giải pháp lót một thông minh" như tôi nghĩ chúng ta sẽ nhận được ... :-) –

+0

+1: quá muộn để trả lời .... –

+0

bạn * có thể * Đặt mọi thứ vào một dòng. nhưng bạn sẽ phải lặp lại cuộc gọi liên kết. mã xấu xí copy'n'paste sau đó :) –

1

Bạn có thể phân lớp, ví dụ: std :: vector :: const_iterator mình, reimplementing operator * và operator-> để trả về giá trị đầu tiên của cặp. Bạn cũng cần tạo các hàm start() và end() của riêng bạn để trả về trình vòng lặp tùy chỉnh của bạn.

Bạn cũng có thể tạo các lớp chức năng nhị phân và chuyển các lớp đó vào inner_product.

+0

Bạn có chắc tôi có thể phân lớp lặp stl? Tôi luôn luôn mặc dù họ đã cung cấp không có destrucor ảo, không cho phép subclassing. –

+0

Tôi không nói subd std :: iterator. Tôi nói subd std :: vector :: const_iterator. Tôi đã thử nó ngay bây giờ, và nó hoạt động. – strager

+0

bạn * có thể * (xin lỗi bình luận của tôi nói "không thể", tôi thực sự có nghĩa là "có thể") phân lớp từ std :: iterator thực sự. nó cung cấp các typedef phổ biến cần thiết. mục đích của nó là không cung cấp một giao diện đa hình –

1

Không có giải pháp một lớp thông minh nào. Hy vọng tốt nhất của bạn là viết trình bao bọc trình bao bọc. Đây thực sự là một giải pháp khá kinh điển. Bạn có thể kiểm tra xem Boost đã có những gì bạn cần. Nếu không, hãy thử viết một wrapper chung có thể được tái sử dụng cho các vấn đề khác.

STL chứa trình bao bọc lặp như vậy được gọi là reverse_iterator. Cái tên ngụ ý việc sử dụng nó.

1

Cuối cùng, tôi nghĩ ý tưởng của bạn là con đường để đi. Bạn có thể sử dụng Boost để giúp bạn làm điều đó. Để bắt đầu, bạn cần một hàm nhận cặp của bạn và trả về phần tử đầu tiên. Tôi nghĩ rằng bạn có thể viết một chức năng như vậy trong dòng bằng cách sử dụng Lambda library, nhưng vì lợi ích của khả năng đọc, tôi nghĩ rằng tôi chỉ cần viết một chức năng đơn giản mà thay vào đó. Sau đó, vượt qua chức năng đó với các trình vòng lặp ban đầu của bạn để xây dựng một transform_iterator để bắt đầu và kết thúc chuỗi của bạn.

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