2009-10-26 17 views
5

Nó được một lúc kể từ Visual Studio thêm hỗ trợ cho một phần mở rộng foreach hoạt động nhưLàm thế nào để viết một lớp có khả năng foreach

vector<int> v(3) 
for each (int i in v) { 
    printf("%d\n",i); 
} 

Tôi muốn biết làm thế nào để thực hiện bất kỳ lớp học có thể sử dụng foreach. Tôi có cần triển khai một số giao diện không?

+0

Trình biên dịch MS không bao giờ hỗ trợ anyting như thế cho mã C++. Tôi đoán bạn đang nói về một số ngôn ngữ khác. C#? Nếu vậy, bạn cần phải gắn thẻ lại câu hỏi của mình. – AnT

+3

http://msdn.microsoft.com/en-us/library/ms177202%28VS.80%29.aspx – stelonix

+2

Có lẽ thẻ C++ phải là thẻ vC++. Điều này chắc chắn không phải là một câu hỏi tiêu chuẩn C++. – MAK

Trả lời

10

for each tuyên bố trong VC++, khi được sử dụng trên một tổ chức phi quản lý lớp:

for each (T x in xs) 
{ 
    ... 
} 

chỉ là cú pháp đường cho việc này:

for (auto iter = xs.begin(), end = xs.end(); iter != end; ++iter) 
{ 
    T x = *iter; 
} 

đâu auto có nghĩa là loại biến được suy luận tự động từ loại khởi tạo.

Nói cách khác, bạn cần phải cung cấp các phương thức begin()end() trên lớp của mình để trả về trình bắt đầu đầu vào và kết thúc cho nó.

Dưới đây là một ví dụ của lớp đó kết thúc tốt đẹp một istream và cho phép bạn duyệt qua tất cả các dòng trong đó:

#include <istream> 
#include <iostream> 
#include <fstream> 
#include <string> 


class lines 
{ 
public: 

    class line_iterator 
    { 
    public: 

     line_iterator() : in(0) 
     { 
     } 

     line_iterator(std::istream& in) : in(&in) 
     { 
      ++*this; 
     } 

     line_iterator& operator++() 
     { 
      getline(*in, line); 
      return *this; 
     } 

     line_iterator operator++ (int) 
     { 
      line_iterator result = *this; 
      ++*this; 
      return result; 
     } 

     const std::string& operator*() const 
     { 
      return line; 
     } 

     const std::string& operator->() const 
     { 
      return line; 
     } 

     friend bool operator== (const line_iterator& lhs, const line_iterator& rhs) 
     { 
      return (lhs.in == rhs.in) || 
        (lhs.in == 0 && rhs.in->eof()) || 
        (rhs.in == 0 && lhs.in->eof()); 
     } 

     friend bool operator!= (const line_iterator& lhs, const line_iterator& rhs) 
     { 
      return !(lhs == rhs); 
     } 

    private: 

     std::istream* const in; 
     std::string line; 
    }; 


    lines(std::istream& in) : in(in) 
    { 
    } 

    line_iterator begin() const 
    { 
     return line_iterator(in); 
    } 

    line_iterator end() const 
    { 
     return line_iterator(); 
    } 

private: 

    std::istream& in; 
}; 


int main() 
{ 
    std::ifstream f(__FILE__); 
    for each (std::string line in lines(f)) 
    { 
     std::cout << line << std::endl; 
    } 
} 

Lưu ý rằng việc thực hiện line_iterator thực sự là hơi lớn hơn mức tối thiểu cần thiết cho for each; Tuy nhiên, nó là việc thực hiện tối thiểu phù hợp với yêu cầu iterator đầu vào, và do đó lớp này cũng là có thể sử dụng với tất cả các thuật toán STL mà làm việc trên lặp đầu vào, chẳng hạn như std::for_each, std::find, vv

+0

bạn có thể đưa ra ví dụ đơn giản nhất của một lớp triển khai các lớp sẽ biên dịch không? Chỉ cần biết các kiểu trả về của phương thức và bất cứ thứ gì khác tôi thiếu, bởi vì tôi không thể biên dịch với một lớp đơn giản – stelonix

+0

Bạn cần cung cấp các trình vòng lặp bắt đầu và kết thúc. – GManNickG

+0

Câu trả lời được cập nhật để bao gồm ví dụ. Các kiểu trả về thực sự không quan trọng, miễn là chúng hỗ trợ tất cả các hoạt động được ngụ ý bằng việc mở rộng mô tả 'cho mỗi'. –

0

foreach không phải là một phần của ngôn ngữ C++ theo như tôi biết. Đó là trong C# mặc dù. Ngoài ra, tôi nghĩ STL và/hoặc Boost có phương pháp foreach. Có lẽ bạn đang nghĩ về điều đó?

+1

Tôi biết nó không phải là một phần của ngôn ngữ và tôi cũng biết rằng có một foreach trong STL và trong Boost. Tuy nhiên, trình biên dịch phòng thu trực quan hỗ trợ foreach theo cách tôi đã trình bày dưới dạng phần mở rộng của trình biên dịch và tôi muốn biết cách tạo các lớp làm việc với nó. – stelonix

+0

Ah được rồi, xin lỗi vì sự hiểu lầm. –

+0

Được bình chọn cho sự hiểu lầm, sau đó xin lỗi vì điều đó? Hóa ra ai đó đã đi trên một spree downvoting. –

1

Bạn có thể sử dụng này

std::for_each

+0

+1 Prefer tiêu chuẩn để mở rộng không chuẩn bất cứ khi nào có thể. –

+3

'std :: for_each' không thực sự là một thay thế bởi vì nó không cho phép bạn chỉ định khối mã để thực thi cho mỗi nội tuyến lặp lại. Trong thực tế, tôi hầu như không bao giờ thấy 'std :: for_each' được sử dụng chính xác vì lý do này - nó chỉ dễ dàng hơn để viết một vòng lặp' for' cũ với các trình vòng lặp. Đối với 'cho mỗi' - nó chắc chắn không có bất kỳ nơi nào trong mã di động, nhưng không phải tất cả các mã đều có ý nghĩa di động. Nếu ứng dụng của bạn đã được viết bằng MFC hoặc ATL, thì bạn vẫn bị mắc kẹt với VC++, và không có gì sai khi sử dụng phần mở rộng ngôn ngữ của nó. –

+0

Vâng, nếu tính di động không phải là một yêu cầu, tôi muốn ném hàm lambda vào hồ bơi và bỏ phiếu cho câu trả lời này. Chúng nhất định sẽ được thực hiện bởi một số trình biên dịch ngay bây giờ hoặc khá sớm, và chúng thực sự sẽ làm cho 'std :: for_each' trở thành giải pháp tốt hơn, vì chúng sẽ trở thành tiêu chuẩn (hy vọng) _all_ trình biên dịch cuối cùng sẽ hỗ trợ. – sbi

-2

Lớp học của bạn nên kế thừa IEnumerable để sử dụng foreach

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