2009-01-20 20 views
12

Làm cách nào để sử dụng BOOST_FOREACH một cách hiệu quả (số lượng ký tự/khả năng đọc khôn ngoan) với tăng :: ptr_map?Cách sử dụng BOOST_FOREACH với tăng :: ptr_map?

Kristo chứng minh trong answer mình rằng nó có thể sử dụng BOOST_FOREACH với một ptr_map, nhưng nó không thực sự tiết kiệm cho tôi bất kỳ gõ (hoặc làm cho mã của tôi thực sự dễ đọc hơn) so với iterating trên ptr_map với một iterator:

typedef boost::ptr_container_detail::ref_pair<int, int* const> IntPair; 
BOOST_FOREACH(IntPair p, mymap) { 
    int i = p.first; 
} 

// vs. 

boost::ptr_map<int, T>::iterator it; 
for (it = mymap.begin(); it != mymap.end(); ++it) { 
    // doSomething() 
} 

Đoạn mã sau nằm ở đâu đó dọc theo những gì tôi muốn. Nó theo cách tiêu chuẩn về cách sử dụng BOOST_FOREACH với một std :: map. Đáng tiếc là điều này không biên dịch:

boost::ptr_map<int, T> mymap; 
// insert something into mymap 
// ... 

typedef pair<int, T> IntTpair; 
BOOST_FOREACH (IntTpair &p, mymap) { 
    int i = p.first; 
} 

Trả lời

16

Như container phong cách STL, các container con trỏ có một typedef value_type mà bạn có thể sử dụng:

#include <boost/ptr_container/ptr_map.hpp> 
#include <boost/foreach.hpp> 

int main() 
{ 
    typedef boost::ptr_map<int, int> int_map; 
    int_map mymap; 

    BOOST_FOREACH(int_map::value_type p, mymap) 
    { 
    } 
} 

tôi thấy rằng sử dụng typedef cho vùng chứa làm cho mã dễ viết hơn rất nhiều.

Ngoài ra, bạn nên cố gắng tránh sử dụng nội dung của các không gian tên detail để tăng cường, đó là quy ước tăng cường rằng chúng chứa chi tiết triển khai.

0

Cần biên dịch mà không có sự tham khảo:

BOOST_FOREACH (IntTpair p, mymap) 

Tôi nghĩ vấn đề là bản đồ không thực sự lưu trữ đối tượng như cặp, nhưng như một cấu trúc cây với người đầu tiên phần tử là khóa, vì vậy BOOST_FOREACH không thể có tham chiếu đến một cặp nhưng nó có thể tạo một bản sao tạm thời của một.

1

này mã ví dụ biên soạn cho tôi với g ++ 4.1.2:

#include "boost/ptr_container/ptr_map.hpp" 
#include "boost/foreach.hpp" 

int main() 
{ 
    boost::ptr_map<int, int> mymap; 

    typedef boost::ptr_container_detail::ref_pair<int, int* const> IntPair; 
    BOOST_FOREACH(IntPair p, mymap) 
    { 
     int i = p.first; 
    } 

    return 0; 
} 
+0

Cảm ơn bạn Kristo, đây là những gì tôi cuối cùng cũng đã đưa ra. Tuy nhiên, đối với điều này phải viết rất nhiều trong typedef, rằng nó không phải là một từ viết tắt thực sự so với tiêu chuẩn cho (ptr_map :: iterator it = mymap.begin(); it! = Mymap.end(); ++ nó) {} nữa ... – Martin

+0

Tôi đồng ý. Tôi quan tâm để xem nếu có một cách ngắn hơn (tốt hơn?) Để viết rằng typedef. Bạn cũng phải xem xét đồng nghiệp của mình. Có bao nhiêu người trong số họ sẽ nói, "Bạn đã viết một typedef điên chỉ để cho bạn sử dụng BOOST_FOREACH? Chỉ cần viết bình thường cho vòng lặp và được thực hiện." :) –

8

Tôi vừa gặp sự cố tương tự ngay hôm nay. Thật không may, đề nghị của Daniel sẽ không làm việc với một tham chiếu liên tục đến một bản đồ. Trong trường hợp của tôi, ptr_map là một thành viên của một lớp, và tôi muốn lặp qua nó trong một hàm thành viên const. Vay dụ Daniel, đây là những gì tôi phải làm gì trong trường hợp của tôi:

#include "boost/ptr_container/ptr_map.hpp" 
#include "boost/foreach.hpp" 

int main() 
{ 
    typedef boost::ptr_map<int, int> int_map; 
    int_map mymap; 
    const int_map& mymap_const_ref(mymap); 

    BOOST_FOREACH(int_map::const_iterator::value_type p, mymap_const_ref) 
    { 
    } 
} 

Dường như int_map::const_iterator::value_type tương đương với boost::ptr_container_detail::ref_pair<int, const int* const>.

0

sử dụng :: value_type sẽ không cho phép bạn const-iterate thông qua vùng chứa. Tôi sử dụng các loại tham chiếu vòng lặp

typedef boost::ptr_map< myKey, myPtrType > MyMap; 
MyMap m; 
BOOST_FOREACH(MyMap::iterator::reference it, m) 
    do_something(it.second); 
BOOST_FOREACH(MyMap::const_iterator::reference it, m) 
    do_something_const(it.second); 
0

Cuối cùng, tôi đã khai báo biến lặp trước vòng lặp.

std::pair<std::string, TrailStep*> step; 
BOOST_FOREACH(step, m_steps) 
{ 
    SAFE_DELETE(step.second); 
} 

Nhưng thực sự, phải có cách đơn giản hơn. (Sử dụng D thay thế?)

1

tôi sử dụng mẫu này homebrew mà thêm một kiểu lặp có thể được xử lý bởi BOOST_FOREACH

namspace homebrew 
{ 
    template 
    < 
    class Key, 
    class T, 
    class Compare  = std::less<Key>, 
    class CloneAllocator = boost::heap_clone_allocator, 
    class Allocator  = std::allocator< std::pair<const Key,void*> > 
    > 
    class ptr_map : 
    public boost::ptr_map<Key,T,Compare,CloneAllocator,Allocator> 
    { 
    public: 
    typedef boost::ptr_container_detail::ref_pair<Key,const T* const> const_ref; 
    typedef boost::ptr_container_detail::ref_pair<Key,T* const> ref; 
    }; 
} 

Giả sử rằng foothanh là hai trong số các loại yêu thích của bạn;)

typedef homebrew::ptr_map<foo,bar> Map; 
int f(const Map& m) 
{ 
    BOOST_FOREACH(Map::const_ref v, m) 
    { 
    v.first; // foo 
    v.second; // const bar* const 
    } 
} 

hoặc

int f(Map& m) 
{ 
    BOOST_FOREACH(Map::ref v, m) 
    { 
    v.first; // foo 
    v.second; // bar* const 
    } 
} 

Loại nào bạn phải sử dụng dường như không phụ thuộc vào cách bạn sử dụng nó trong vòng lặp (const hoặc không const) nhưng trên bản đồ của constness !! Vì vậy, sau đây sẽ kết thúc trong một lỗi ...

int f(Map& m) 
{ 
    BOOST_FOREACH(Map::const_ref v, m) // can't use const_ref because m isn't const 
    { 
    ... 
    } 
} 

Lạ! phải không?

Điều quan trọng nhất đối với tôi là tất cả các giải pháp được đề xuất ở đây, đây là giải pháp đầu tiên được xử lý chính xác bằng màu cú pháp CDT của Eclipse (khi sử dụng thuộc tính tô màu cú pháp 'Code/Problem').

0

Bạn có thể thử cách uber-mát này để lặp qua bản đồ, ptr hoặc: https://svn.boost.org/trac/boost/attachment/ticket/3469/foreach_field.hpp

// no typedef needed 
BOOST_FOREACH_FIELD((int i)(const T& t), mymap) 
    // do something with i or t instead of first/second 

Tôi không chắc chắn nó sẽ làm việc với một tham số mẫu, nhưng có lẽ bạn sử dụng mà chỉ dành riêng cho trừu tượng.

6

Lưu mình những đánh máy và cải thiện khả năng đọc bằng cách sử dụng các bộ:

boost::ptr_map<int, T> mymap; 
int key; 
T * value; 
BOOST_FOREACH(boost::tie(key, value), mymap) 
{ 
    ... 
} 
+0

Đã bao giờ biên dịch chưa? Đi qua mã lịch sử của cả 'tuple' và' ptr_container', tôi không thể giúp kết luận nó không thể (và bất kỳ nỗ lực nào để làm như vậy đều thất bại). Xem [câu hỏi liên quan này] (https://stackoverflow.com/questions/44588615/why-doesnt-boosttie-work-with-boost-foreach). –

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