blob: ef4e140d0cbf6b917aec3b79fc877c9d6ce57852 [file]
// 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_