2009-07-09 69 views
11

tôi có:"Chung" iterator trong C++

void add_all_msgs(std::deque<Message>::iterator &iter); 

Làm thế nào tôi có thể làm cho rằng chức năng "chung chung", vì vậy nó có thể mất bất kỳ loại inputiterators? Tôi không thực sự quan tâm nếu nó lặp lại một deque, một vector hoặc cái gì khác, miễn là iterator là iterating của tin nhắn. - là điều này ở tất cả thẳng về phía trước có thể trong c + +?

Trả lời

6
template<class InputIterator> 
void add_all_msgs(InputIterator iter); 

Cách sử dụng:

std::deque<Message> deq; 
add_all_msgs(deq.begin()); 
+5

Công ước sẽ lấy vòng lặp theo giá trị thay vì tham chiếu.Bên cạnh đó iterators thường là "nhỏ" anyway, lý do cho điều này (afaik) là để cho phép người gọi để vượt qua một tạm thời, chẳng hạn như một giá trị trả về từ std :: back_inserter. C++ 0x giúp với điều này trong ít nhất hai cách tôi có thể nghĩ đến. –

+0

Heh, hoặc giá trị trả về từ "bắt đầu" đến để suy nghĩ về nó. Mã "sử dụng" ở trên không biên dịch: "khởi tạo không hợp lệ tham chiếu không const của loại 'blah' từ tạm thời kiểu 'blah'". –

+1

OP rõ ràng đã nói: "miễn là người lặp lại đang lặp lại Thông báo". Giải pháp này, và hầu hết những người khác, hoàn toàn bỏ qua yêu cầu này. –

0
#include <deque> 
#include <vector> 
#include <list> 
#include <string> 
using namespace std; 

template<typename T> 
void add_all_msgs(T &iter) 
{ 

} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::deque<string>::iterator it1; 
    std::vector<string>::iterator it2; 
    std::list<string>::iterator it3; 

    add_all_msgs(it1); 
    add_all_msgs(it2); 
    add_all_msgs(it3); 


    return 0; 
} 
+0

Và add_all_msgs phải là mẫu nhiều hơn hoặc ít hơn? Các vòng lặp không phải là "đa hình"? – nos

+0

@noselasd: Các trình vòng lặp không xuất phát từ một lớp cơ sở chung, nếu đó là ý của bạn. –

+0

Vì vậy, chúng _are_ đa hình (thông qua gõ vịt tĩnh), chỉ cần không theo cách bạn có thể nghĩ về đa hình trong, nói, Java. –

12
template <typename Iterator> 
void add_all_messages(Iterator first, Iterator last) 

sử dụng:

vector<message> v; 
add_all_messages(v.begin(), v.end()); 

Bạn cần phải xác định cuối cùng, nếu không bạn sẽ không biết khi nào nên dừng lại! Nó cũng mang lại cho bạn sự linh hoạt khi chỉ thêm một vùng phụ của một vùng chứa.

+0

Vâng, tôi thực sự giả định (không giống như aJ) rằng trình lặp được sử dụng như một trình lặp đầu ra, trong trường hợp này, trình lặp kết thúc là thừa. :-P –

+0

Ồ chờ đã, OP cho biết đó là trình lặp đầu vào. Điểm lấy. :-P –

5

Nếu bạn muốn trình biên dịch kiểm tra xem trình vòng lặp có thực sự đề cập đến các đối tượng Message không, bạn có thể sử dụng một kỹ thuật như sau.

template <typename InputIterator, typename ValueType> 
struct AddAllMessages { }; 

template <typename InputIterator> 
struct AddAllMessages<InputIterator, Message> { 
    static void execute(const InputIterator &it) { 
    // ... 
    } 
}; 

template <typename InputIterator> 
void add_all_msgs(const InputIterator &it) { 
    AddAllMessages<InputIterator, 
       typename std::iterator_traits<InputIterator>::value_type>::execute(it); 
} 
1

Hơi đơn giản rằng ở trên (ở chỗ nó thúc đẩy các thư viện hiện có):

#include <boost/static_assert.hpp> // or use C++0x static_assert 
#include <boost/type_traits/is_same.hpp> 

template <typename InputIterator> 
void add_all_msgs(InputIterator it) { 
    BOOST_STATIC_ASSERT((boost::is_same< 
     typename std::iterator_traits<InputIterator>::value_type, 
     Message>::value)); 
    // ... 
2

Nếu bạn không muốn templatize chức năng add_all_msgs của bạn, bạn có thể sử dụng adobe::any_iterator:

typedef adobe::any_iterator<Message, std::input_iterator_tag> any_message_iterator; 
void add_all_msgs(any_message_iterator begin, any_message_iterator end); 
+0

Tiện lợi. [15chars] –

+0

Tôi sẽ đi với templating các add_all_msgs cho bây giờ, mặc dù đây là những gì tôi muốn lý tưởng. – nos

+2

Phiên bản mẫu chắc chắn hiệu quả hơn, với any_iterator bạn có một cuộc gọi hàm ảo trên mọi thao tác (tức là di chuyển đến vị trí tiếp theo và dereferencing) so với cuộc gọi hàm inline'd. –

1

Thật khó để có đa hình động với các trình lặp vòng kiểu C++. operator++(int) trả về theo giá trị, mà afaik là không thể nhận được: bạn không thể có hàm thành viên ảo trả về *this theo giá trị mà không bị cắt.

Nếu có thể, tôi khuyên bạn nên sử dụng các mẫu như những người khác nói.

Tuy nhiên nếu bạn làm cần đa hình năng động, ví dụ bởi vì bạn không thể phơi bày việc thực hiện add_all_msgs làm mẫu sẽ làm gì, sau đó tôi nghĩ rằng bạn có thể giả vờ là Java, như thế này:

struct MessageIterator { 
    virtual Message &get() = 0; 
    virtual void next() = 0; 
    // add more functions if you need more than a Forward Iterator. 
    virtual ~MessageIterator() { }; // Not currently needed, but best be safe 
}; 

// implementation elsewhere. Uses get() and next() instead of * and ++ 
void add_all_msgs(MessageIterator &it); 

template <typename T> 
struct Adaptor : public MessageIterator { 
    typename T::iterator wrapped; 
    Adaptor(typename T::iterator w) : wrapped(w) { } 
    virtual Message &get() { 
     return *wrapped; 
    } 
    virtual void next() { 
     ++wrapped; 
    } 
}; 

int main() { 
    std::deque<Message> v; 
    Adaptor<std::deque<Message> > a(v.begin()); 
    add_all_msgs(a); 
} 

Tôi đã kiểm tra rằng biên dịch này, nhưng tôi đã không kiểm tra nó và tôi chưa bao giờ sử dụng thiết kế này trước đây. Tôi cũng không làm phiền với const-ness - trong thực tế bạn có thể muốn có một const Message &get() const. Và tại thời điểm bộ điều hợp không có cách nào để biết khi nào nên dừng lại, nhưng sau đó cũng không phải mã bạn bắt đầu, vì vậy tôi cũng đã bỏ qua điều đó. Về cơ bản, bạn cần có hàm hasNext so sánh wrapped với trình lặp kết thúc được cung cấp cho hàm tạo.

Bạn có thể làm điều gì đó với chức năng mẫu và tham chiếu const để khách hàng không phải biết hoặc khai báo loại Bộ điều hợp khó chịu đó.

[Chỉnh sửa: suy nghĩ về điều đó, có lẽ tốt hơn là nên có một mẫu hàm add_all_msgs sơ khai, bao bọc thông số của nó trong Bộ điều hợp và sau đó gọi real_add_all_msgs. Điều này hoàn toàn ẩn bộ điều hợp từ phía máy khách.]