Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

Reverse Range-based For Loop ใน C++: ใช้ Boost และ C++20

C++ Range-based For Loop (for (auto& x : container)) รองรับเฉพาะ Forward Iteration ตั้งแต่ C++11 หากต้องการ Iterate ย้อนหลัง (Reverse) มีหลายวิธี

1. ใช้ Boost.Range (Classic Solution)

Header: <boost/range/adaptor/reversed.hpp>

#include <iostream>
#include <vector>
#include <boost/range/adaptor/reversed.hpp>

int main() {
    std::vector<int> v = {11, 44, 77, 55, 44, 22, 33, 30, 88, 99, 55, 44};

    std::cout << "Normal: ";
    for (auto i : v) std::cout << i << ' ';
    std::cout << '\n';

    std::cout << "Reversed: ";
    for (auto i : boost::adaptors::reverse(v)) 
        std::cout << i << ' ';
    // Output: 44 55 99 88 30 33 22 44 55 77 44 11
}

2. ใช้ C++20: std::views::reverse (Standard, Header <ranges>)

#include <iostream>
#include <vector>
#include <ranges> // C++20

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    std::cout << "Reversed (C++20): ";
    for (auto i : v | std::views::reverse) 
        std::cout << i << ' '; // 5 4 3 2 1
}

3. Manual Reverse Iterator (No Dependency, Pre-C++20)

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    // Classic Reverse Iterator
    std::cout << "Reverse Iterator: ";
    for (auto it = v.rbegin(); it != v.rend(); ++it)
        std::cout << *it << ' ';

    // Index-based (ถ้าต้องการ Index)
    std::cout << "\nIndex Reverse: ";
    for (size_t i = v.size(); i-- > 0; ) 
        std::cout << v[i] << ' ';
}

4. Custom Reverse View (C++17, No Boost)

#include <iostream>
#include <vector>
#include <iterator>

template <typename Container>
class ReverseView {
    Container& c;
public:
    ReverseView(Container& c) : c(c) {}
    auto begin() const { return c.rbegin(); }
    auto end() const { return c.rend(); }
};

template <typename C>
ReverseView<C> make_reverse(C& c) { return ReverseView<C>(c); }

// Usage
int main() {
    std::vector<int> v = {1,2,3,4,5};
    for (auto i : make_reverse(v)) std::cout << i << ' ';
}

ตารางเปรียบเทียบ

วิธีStandardDependencyReadabilityPerformance
Boost::adaptors::reverse❌Boost⭐⭐⭐⭐⭐Zero Overhead
std::views::reverse (C++20)✅None⭐⭐⭐⭐⭐Zero Overhead
Reverse Iterator (rbegin/rend)✅ (C++98)None⭐⭐⭐Zero Overhead
Index Loop (size_t i = n; i--;)✅None⭐⭐Zero Overhead

ข้อระวัง

  • Range-based For ต้องการ begin() และ end() (Non-const สำหรับ Mutable)
  • boost::adaptors::reverse และ std::views::reverse คืน View (Lazy, No Copy)
  • Container ต้องมี rbegin()/rend() (Vector, List, Deque, String, Array - แต่ไม่ใช่ Forward List)

สรุป

C++20 std::views::reverse เป็นคำตอบมาตรฐานที่ดีที่สุด ก่อน C++20 ใช้ boost::adaptors::reverse หรือ Manual Reverse Iterator ทั้งคู่ Zero Overhead Abstraction เลือกตาม Compiler Support และ Dependency Policy ของโปรเจกต์