2008-10-13 26 views
23

Tôi chỉ mới phát hiện ra rằng Visual C++ 2008 (và có lẽ phiên bản cũ hơn?) Hỗ trợ cú pháp for each trên danh sách stl et al để tạo điều kiện lặp lại. Ví dụ:Visual C++ "cho mỗi" tính di động

list<Object> myList; 

for each (Object o in myList) 
{ 
    o.foo(); 
} 

Tôi đã rất vui khi khám phá nó, nhưng tôi lo ngại về tính di động cho ngày đáng sợ khi ai đó quyết định tôi cần để có thể biên dịch mã của tôi trong tiếng nói, gcc hoặc một số trình biên dịch khác . Cú pháp này có được hỗ trợ rộng rãi và tôi có thể sử dụng nó mà không lo lắng về các vấn đề về tính di động không?

Trả lời

25

Đối với mỗi loại không phải là cú pháp C hoặc C++ chuẩn. Nếu bạn muốn có thể biên dịch mã này trong gcc hoặc g ++, bạn sẽ cần phải tạo một trình lặp và sử dụng một tiêu chuẩn cho vòng lặp.

QuantumPete

[sửa] này có vẻ là một tính năng mới được giới thiệu vào MS Visual C++, vì vậy đây chắc chắn không phải là cầm tay. Tham khảo: http://msdn.microsoft.com/en-us/library/xey702bw%28VS.80%29.aspx [/ chỉnh sửa]

21

Có một giải pháp thay thế di động rất tốt: Boost.Foreach. Chỉ cần đổ tiêu đề này vào dự án của bạn và bạn có thể viết các vòng lặp của bạn như sau:

list<Object> myList; 

BOOST_FOREACH(Object o, myList) 
    o.foo(); 
5

Visual C++ "cho mỗi" không phải là tiêu chuẩn C++, có nghĩa là bạn sẽ không thể để biên dịch mã của bạn trên các trình biên dịch khác như g ++. Tuy nhiên, STL đề xuất std::for_each, nhưng cú pháp của nó ít trực quan hơn nhiều. Đây là nguyên mẫu của nó:

template <class InputIterator, class UnaryFunction> 
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f); 

Phải mất hai vòng lặp xác định phạm vi hợp lệ và áp dụng hàm unary (hoặc functor) f cho từng đối tượng trong phạm vi này. Bạn có thể viết lại ví dụ của bạn sử dụng std :: for_each như thế này:

void foo(Object o) 
{ 
    o.foo(); 
} 
... 
list<Object> myList; 

std::for_each(myList.begin(), myList.end(), foo); 

Tuy nhiên, nếu bạn muốn ở lại gần với cú pháp cổ điển của cho mỗi cấu trúc, và nếu bạn ok về việc sử dụng Boost, bạn có thể sử dụng BOOST.FOREACH, mà sẽ cho phép bạn viết

list<Object> myList; 

BOOST_FOREACH(Object o, myList) 
{ 
    o.foo(); 
} 
+2

Lưu ý: cho mỗi (a trong b) có vẻ là CLR chỉ ngay cả trong VS 2005/2008 - bạn không thể sử dụng nó trong mã gốc, chỉ khi nhắm mục tiêu .NET, làm cho mỗi thậm chí "ít di động". Nếu không, tôi nghĩ câu trả lời của bạn là tuyệt vời. – Suma

+0

Cũng lưu ý rằng nếu bạn đang sử dụng VS2010, bạn có lambdas và std :: for_each() đột nhiên trở nên dễ đọc. – Luis

-1

phiếu bầu của tôi đi cho Lức,

Stick để các thuật toán tiêu chuẩn STL và bạn sẽ được tốt hơn bởi đến nay. Thuật toán STL có thể làm cho cuộc sống của bạn trở nên dễ dàng, hiệu quả và an toàn. Hãy nhìn vào tắt các thuật toán xiên như find_if, đếm, count_if, sắp xếp, chuyển đổi, vv ...

điểm 5 trở đi ... http://www.sgi.com/tech/stl/table_of_contents.html

Boost là mát mẻ, nhưng nếu bạn đang đi để sử dụng nó chỉ cho macro FOR_EACH nó là quá nhiều cồng kềnh liên quan đến việc phát triển/xây dựng môi trường thiết lập.

sử dụng tăng khi tiêu chuẩn C++/stl không thể giải quyết vấn đề theo cách 'dễ dàng'.

0

Tôi cũng khuyên bạn nên BOOST_FOREACH. Tôi thường tạo macro dọc theo các dòng:

#define _foreach(x,y) BOOST_FOREACH(x,y) 

Điều này có xu hướng tăng khả năng đọc.Bạn phải cẩn thận về những va chạm với việc triển khai foreach khác. Ví dụ, Qt cung cấp một 'foreach' và có std :: for_each.

Tôi thấy rằng tiêu chuẩn :: for_each không thực sự tiết kiệm nhiều thời gian kể từ khi bạn kết thúc việc tạo nhiều đối tượng chức năng một lần để cung cấp cho cuộc gọi for_each. Nó thường là nhanh để tạo ra vòng lặp chuẩn sử dụng các trình lặp STL.

+4

Trong tài liệu Boost.Foreach, họ đã tư vấn rõ ràng cách bạn viết định nghĩa của mình. Thay vào đó, hãy viết "#define _foreach BOOST_FOREACH". –

+0

Tôi thích giữ nó như BOOST_FOREACH đơn giản chỉ vì nó nhắc nhở rằng đó là một sự mở rộng vĩ mô và phải cẩn thận về những gì tôi đặt bên trong nó. – Ferruccio

30

Tôi sẽ không sử dụng điều đó. Mặc dù đó là một tính năng hấp dẫn, cú pháp không tương thích với tiêu chuẩn C++ 0x sắp tới, sử dụng:

list<Object> myList; 

for (Object o : myList) 
{ 
    o.foo(); 
} 

để làm điều tương tự.

6

Nếu bạn muốn sử dụng foreach và trong cùng một thời điểm bạn không muốn thêm phụ thuộc bổ sung (như Boost) - macro này sẽ giúp bạn:

#define VAR(V,init) __typeof(init) V=(init) 
#define FOREACH(I,C) for(VAR(I,(C).begin());I!=(C).end();I++) 

std::vector<int> numbers; 

FOREACH(I, numbers) 
{ 
    std::cout << *I << std::endl; 
} 
1

Mã của bạn thực sự là không di động.

Các công trình sau đây có tiêu chuẩn C++ 0x và Visual C++ 2010 (không hỗ trợ cú pháp "tầm xa" mới theo như tôi có thể biết).

#define for_each(_ITER_, _COLL_) for (auto _ITER_ = _COLL_.begin(); \ 
    _ITER_ != _COLL_.end(); _ITER_++) 

Bây giờ bạn có thể viết:

list<Object> myList; 

for_each (o, myList) 
{ 
    o.foo(); 
} 

Hãy so sánh này để mã vĩ mô BOOST_FOREACH tại http://www.boost.org/doc/libs/1_48_0/boost/foreach.hpp đó là không chỉ phức tạp nó cũng có một số phụ thuộc vào thư viện tăng khác.

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