std::for_each(A.rbegin(), A.rend(), [](int i) { /*code*/ });
sự là giải pháp đơn giản.
tôi thay vì đã viết backwards
mà phải mất một chuỗi, chiết xuất các begin
và end
iterator từ nó bằng cách sử dụng miễn phí begin
và end
chức năng (với std::begin
và std::end
using
tờ khai lân cận - đầy đủ ADL), tạo ra vòng lặp ngược xung quanh họ, sau đó trả về một chuỗi với hai trình lặp ngược này.
Nó là loại gọn gàng, bởi vì bạn sẽ có được cú pháp sau:
for(int i : backwards(A)) {
// code
}
mà tôi tìm thấy dễ dàng hơn để đọc hơn std::for_each
hoặc bằng tay for
vòng.
Nhưng tôi hơi điên.
Dưới đây là số tối thiểu backwards
. Một giải pháp đầy đủ về xử lý adl và một vài trường hợp góc tốt hơn.
template<class It, class C>
struct range_for_t{
It b,e;
C c; // for lifetime
It begin()const{return b;}
It end()const{return e;}
}
template<class It, class C>
range_for_t<It,C> range_for(It b,It e,C&& c){
return {std::move(b),std::move(e),std::forward<C>(c)};
}
template<class It>
range_for_t<It,int> range_for(It b,It e){
return {std::move(b),std::move(e)};
}
Phạm vi đơn giản cho phạm vi chỉ. Có thể được tăng cường với chuyển tiếp hoàn hảo.
Chuyển C
làm vùng chứa có thể cần kéo dài suốt đời. Nếu được thông qua như rvalue, sao chép được thực hiện, nếu không chỉ cần tham khảo. Nó không được sử dụng.
phần tiếp theo là dễ dàng:
template<class It>
auto reverse_it(It it){
return std::reverse_iterator<It>(std::move(it));
}
template<class C>
auto backwards(C&&c){
using std::begin; using std::end;
auto b=begin(c), e=end(c);
return range_for(
reverse_it(e),reverse_it(b),
std::forward<C>(c)
);
}
Đó là chưa được kiểm tra nhưng nên làm việc.
Một thử nghiệm quan trọng là đảm bảo nó hoạt động khi bạn ăn một vec rvalue như:
for(auto x:backwards(make_vec()))
công trình - đó là những gì mà lộn xộn xung quanh lưu trữ C
là về. Nó cũng giả định rằng các trình vòng lặp container được chuyển đổi có các trình vòng lặp hoạt động độc đáo.
Bạn đảo ngược Rend và rbegin. – Borgleader
@Borgleader Có, bạn đã đúng. Cảm ơn. – user350954