Trên thực tế, trong C++ 14 nó có thể được thực hiện với một số rất ít dòng mã.
Đây là một ý tưởng rất giống với giải pháp @ Paul. Do những điều thiếu trong C++ 11, giải pháp đó là một chút không cần thiết cồng kềnh (cộng với việc xác định mùi hôi thối). Nhờ C++ 14 chúng tôi có thể làm cho nó dễ đọc hơn nhiều.
Quan sát chính là các vòng lặp dựa trên phạm vi hoạt động bằng cách dựa trên begin()
và end()
để có được trình vòng lặp của phạm vi. Nhờ có ADL, bạn thậm chí không cần phải xác định begin()
và end()
tùy chỉnh trong không gian tên std :: của mình.
Dưới đây là một giải pháp rất đơn giản-mẫu:
// -------------------------------------------------------------------
// --- Reversed iterable
using std::rbegin,
std::rend;
template <typename T>
struct reversion_wrapper { T& iterable; };
template <typename T>
auto begin (reversion_wrapper<T> w) { return rbegin(w.iterable); }
template <typename T>
auto end (reversion_wrapper<T> w) { return rend(w.iterable); }
template <typename T>
reversion_wrapper<T> reverse (T&& iterable) { return { iterable }; }
này hoạt động như một nét duyên dáng, ví dụ:
template <typename T>
void print_iterable (ostream& out, const T& iterable)
{
for (auto&& element: iterable)
out << element << ',';
cout << '\n';
}
int main (int, char**)
{
// on prvalues
print_iterable(cout, reverse(initializer_list<int> { 1, 2, 3, 4, }));
// on const lvalue references
const list<int> ints_list { 1, 2, 3, 4, };
for (auto&& el: reverse(ints_list))
cout << el << ',';
cout << '\n';
// on mutable lvalue references
vector<int> ints_vec { 0, 0, 0, 0, };
size_t i = 0;
for (int& el: reverse(ints_vec))
el += i++;
print_iterable(cout, ints_vec) << '\n';
print_iterable(cout, reverse(ints_vec)) << '\n';
return 0;
}
in như mong đợi
4,3,2,1,
4,3,2,1,
3,2,1,0,
0,1,2,3,
LƯU Ýstd::rbegin()
, std::rend()
và std::make_reverse_iterator()
chưa được triển khai trong GCC-4.9. Tôi viết những ví dụ này theo tiêu chuẩn, nhưng chúng sẽ không biên dịch trong g ++ ổn định. Tuy nhiên, việc thêm các nhánh tạm thời cho ba hàm này là rất dễ dàng.Đây là một thực hiện mẫu, chắc chắn không phải hoàn nhưng hoạt động tốt đủ cho hầu hết các trường hợp:
// --------------------------------------------------
template <typename I>
reverse_iterator<I> make_reverse_iterator (I i)
{
return std::reverse_iterator<I> { i };
}
// --------------------------------------------------
template <typename T>
auto rbegin (T& iterable)
{
return make_reverse_iterator(iterable.end());
}
template <typename T>
auto rend (T& iterable)
{
return make_reverse_iterator(iterable.begin());
}
// const container variants
template <typename T>
auto rbegin (const T& iterable)
{
return make_reverse_iterator(iterable.end());
}
template <typename T>
auto rend (const T& iterable)
{
return make_reverse_iterator(iterable.begin());
}
CẬP NHẬT 22 Oct 2017
Nhờ estan cho trỏ này ra.
Thực hiện mẫu câu trả lời ban đầu sử dụng using namespace std;
, điều này sẽ gây ra bất kỳ tệp nào bao gồm việc triển khai này (phải nằm trong tệp tiêu đề), cũng nhập toàn bộ không gian tên std
.
Sửa đổi triển khai mẫu để đề xuất using std::rbegin, std::rend
thay thế.
Một bộ chuyển đổi chứa ngược lại, có vẻ thú vị, nhưng tôi nghĩ rằng bạn sẽ phải viết nó cho mình. Chúng tôi sẽ không có vấn đề này nếu Ủy ban tiêu chuẩn sẽ nhanh chóng và điều chỉnh các thuật toán dựa trên phạm vi thay vì các trình vòng lặp rõ ràng. –
@ Tôi biết tôi có thể viết nó, nhưng đó không phải là vấn đề. Nếu tôi viết nó, nó sẽ trở thành một trong những chức năng hữu ích mà không thuộc bất kỳ nơi nào đặc biệt (tm), vì vậy bạn kết thúc việc viết mã của bạn với phần đầu tiện ích đã biết và trộn hệ thống xây dựng của bạn để chia sẻ nó qua các dự án . Bởi lý do này, chúng ta vẫn nên sử dụng BOOST_FOREACH thay vì phạm vi cho. Và vâng, tôi lười biếng. –
@deft_code: "thay vì?" Tại sao bạn muốn loại bỏ các thuật toán dựa trên iterator? Chúng tốt hơn và ít chi tiết hơn đối với các trường hợp bạn không lặp lại từ 'begin' to' end', hoặc để xử lý các trình lặp dòng và tương tự. Phạm vi thuật toán sẽ là tuyệt vời, nhưng họ đang thực sự chỉ cú pháp đường (ngoại trừ khả năng đánh giá lười biếng) trên các thuật toán lặp. –