| // Copyright 2026 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef TOOLS_GN_RANGE_UTILS_H_ |
| #define TOOLS_GN_RANGE_UTILS_H_ |
| |
| #include <concepts> |
| #include <ranges> |
| #include <vector> |
| |
| template <typename R, typename T> |
| concept RangeOf = std::ranges::input_range<R> && |
| std::convertible_to<std::ranges::range_reference_t<R>, T>; |
| |
| // std::ranges::to<std::vector> should be preferred, but isn't available on the |
| // older versions of mac used in CI. |
| template <std::ranges::input_range R> |
| auto to_vec(R&& range) { |
| using ValType = std::ranges::range_value_t<R>; |
| // For common ranges (where begin() and end() return the same type, such as |
| // std::vector or simple views), we can use std::vector's iterator |
| // constructor. |
| if constexpr (std::ranges::common_range<R>) { |
| return std::vector<ValType>(range.begin(), range.end()); |
| } else { |
| // For non-common ranges (where begin() and end() have different types, such |
| // as lazy split views or generators using sentinels), std::vector's |
| // iterator constructor will fail to compile. We must use a range-based for |
| // loop, which natively supports sentinel comparisons of different types. |
| std::vector<ValType> vec; |
| if constexpr (std::ranges::sized_range<R>) { |
| vec.reserve(std::ranges::size(range)); |
| } |
| for (auto&& item : range) { |
| vec.push_back(std::forward<decltype(item)>(item)); |
| } |
| return vec; |
| } |
| } |
| |
| #endif // TOOLS_GN_RANGE_UTILS_H_ |