diff --git a/libs/libvtrutil/src/vtr_vector.h b/libs/libvtrutil/src/vtr_vector.h index dcf783abe99..be4e5874e98 100644 --- a/libs/libvtrutil/src/vtr_vector.h +++ b/libs/libvtrutil/src/vtr_vector.h @@ -4,6 +4,8 @@ #include #include #include +#include + #include "vtr_range.h" namespace vtr { @@ -56,9 +58,6 @@ class vector : private std::vector { class key_iterator; typedef vtr::Range key_range; - class pair_iterator; - typedef vtr::Range pair_range; - public: //Pass through std::vector's types using typename storage::allocator_type; @@ -157,16 +156,41 @@ class vector : private std::vector { } /** - * @brief Returns a range containing the key-value pairs. + * @brief Provides an iterable object to enumerate the vector. + * + * This function allows for easy enumeration, yielding a tuple of (index, element) + * pairs in each iteration. It is similar in functionality to Python's `enumerate()`. + * This function can be used in range-based with structured binding to iterate over + * indices and values at the same time. * - * This function returns a range object that represents the sequence of key-value - * pairs within the vector. The range can be used to iterate over the pairs using - * standard range-based loops or algorithms. + * vtr::vector vec; + * for (const auto& [idx, value] : vec) { + * ... + * } + * It should be noted that value is returned by reference even if "&" + * does not appear after auto keyword. However, it is recommended to use "&" + * explicitly to avoid any confusion about value's scope. * - * @return A `pair_range` object representing the range of key-value pairs. + * @ return An iterable wrapper that can be used in a range-based for loop to obtain + * (index, element) pairs. */ - pair_range pairs() const { - return vtr::make_range(pair_begin(), pair_end()); + auto pairs() const { + struct enumerated_iterator { + key_type i; + vector::const_iterator iter; + + bool operator!=(const enumerated_iterator& other) const { return iter != other.iter; } + void operator++() { i = key_type(size_t(i) + 1); iter++; } + std::tuple operator*() { return std::tie(i, *iter); } + }; + + struct enumerated_wrapper { + const vector& vec; + auto begin() { return enumerated_iterator{ key_type(0), vec.begin() }; } + auto end() { return enumerated_iterator{ key_type(vec.size()), vec.end() }; } + }; + + return enumerated_wrapper{ *this }; } public: @@ -218,59 +242,9 @@ class vector : private std::vector { value_type value_; }; - /** - * @brief A bidirectional iterator for a vtr:vector object. - * - * The `pair_iterator` class provides a way to iterate over key-value pairs - * within a vtr::vector container. It supports bidirectional iteration, - * allowing the user to traverse the container both forwards and backwards. - */ - class pair_iterator { - public: - using iterator_category = std::bidirectional_iterator_tag; - using difference_type = std::ptrdiff_t; - using value_type = std::pair; - using pointer = value_type*; - using reference = value_type&; - - /// @brief constructor - pair_iterator(vector& vec, key_type init) - : vec_(vec), value_(init, vec[init]) {} - - /// @brief ++ operator - pair_iterator& operator++() { - value_ = std::make_pair(key_type(size_t(value_.first) + 1), vec_[key_type(size_t(value_.first) + 1)]); - return *this; - } - /// @brief -- operator - pair_iterator& operator--() { - value_ = std::make_pair(key_type(size_t(value_.first) - 1), vec_[key_type(size_t(value_.first) - 1)]); - return *this; - } - /// @brief dereference operator - reference operator*() { return value_; } - /// @brief -> operator - pointer operator->() { return &value_; } - - /// @brief == operator - friend bool operator==(const pair_iterator& lhs, const pair_iterator& rhs) { return lhs.value_.first == rhs.value_.first; } - /// @brief != operator - friend bool operator!=(const pair_iterator& lhs, const pair_iterator& rhs) { return !(lhs == rhs); } - - private: - /// @brief Reference to the vector of key-value pairs. - vector& vec_; - // @brief The current key-value pair being pointed to by the iterator. - value_type value_; - }; - private: key_iterator key_begin() const { return key_iterator(key_type(0)); } key_iterator key_end() const { return key_iterator(key_type(size())); } - - pair_iterator pair_begin() const { return pair_iterator(*const_cast*>(this), key_type(0)); } - pair_iterator pair_end() const { return pair_iterator(*const_cast*>(this), key_type(size())); } }; - } // namespace vtr #endif diff --git a/vpr/test/test_odd_even_routing.cpp b/vpr/test/test_odd_even_routing.cpp index e642518076b..c0cf9278bee 100644 --- a/vpr/test/test_odd_even_routing.cpp +++ b/vpr/test/test_odd_even_routing.cpp @@ -5,6 +5,7 @@ #include "channel_dependency_graph.h" #include +#include namespace { @@ -225,7 +226,7 @@ TEST_CASE("test_route_flow", "[vpr_noc_odd_even_routing]") { compare_routes(golden_path, found_path, noc_model); } - SECTION("Test case where multiple traffic flows are router, and routes are checked for turn legality and deadlock freedom.") { + SECTION("Test case where multiple traffic flows are routed, and routes are checked for turn legality and deadlock freedom.") { std::random_device device; std::mt19937 rand_num_gen(device()); std::uniform_int_distribution dist(0, 99); @@ -248,7 +249,6 @@ TEST_CASE("test_route_flow", "[vpr_noc_odd_even_routing]") { vtr::vector> traffic_flow_routes(traffic_flow_storage.get_number_of_traffic_flows()); for (const auto& [id, traffic_flow] : traffic_flow_storage.get_all_traffic_flows().pairs()) { - NocRouterId src_router_id = noc_model.get_router_at_grid_location(block_locs[traffic_flow.source_router_cluster_id].loc); NocRouterId dst_router_id = noc_model.get_router_at_grid_location(block_locs[traffic_flow.sink_router_cluster_id].loc);