// Copyright 2020 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 BASE_RANGES_RANGES_H_ #define BASE_RANGES_RANGES_H_ #include #include #include #include #include "base/template_util.h" namespace base { namespace internal { // Overload for C array. template constexpr T* begin(T (&array)[N], priority_tag<2>) { return array; } // Overload for mutable std::array. Required since std::array::begin is not // constexpr prior to C++17. Needs to dispatch to the const overload since only // const operator[] is constexpr in C++14. template constexpr T* begin(std::array& array, priority_tag<2> tag) { return const_cast(begin(const_cast&>(array), tag)); } // Overload for const std::array. Required since std::array::begin is not // constexpr prior to C++17. template constexpr const T* begin(const std::array& array, priority_tag<2>) { return N != 0 ? &array[0] : nullptr; } // Generic container overload. template constexpr auto begin(Range&& range, priority_tag<1>) -> decltype(std::forward(range).begin()) { return std::forward(range).begin(); } // Overload for free begin() function. template constexpr auto begin(Range&& range, priority_tag<0>) -> decltype(begin(std::forward(range))) { return begin(std::forward(range)); } // Overload for C array. template constexpr T* end(T (&array)[N], priority_tag<2>) { return array + N; } // Overload for mutable std::array. Required since std::array::end is not // constexpr prior to C++17. Needs to dispatch to the const overload since only // const operator[] is constexpr in C++14. template constexpr T* end(std::array& array, priority_tag<2> tag) { return const_cast(end(const_cast&>(array), tag)); } // Overload for const std::array. Required since std::array::end is not // constexpr prior to C++17. template constexpr const T* end(const std::array& array, priority_tag<2>) { return N != 0 ? (&array[0]) + N : nullptr; } // Generic container overload. template constexpr auto end(Range&& range, priority_tag<1>) -> decltype(std::forward(range).end()) { return std::forward(range).end(); } // Overload for free end() function. template constexpr auto end(Range&& range, priority_tag<0>) -> decltype(end(std::forward(range))) { return end(std::forward(range)); } } // namespace internal namespace ranges { // Simplified implementation of C++20's std::ranges::begin. // As opposed to std::ranges::begin, this implementation does does not check // whether begin() returns an iterator and does not inhibit ADL. // // The trailing return type and dispatch to the internal implementation is // necessary to be SFINAE friendly. // // Reference: https://wg21.link/range.access.begin template constexpr auto begin(Range&& range) noexcept -> decltype(internal::begin(std::forward(range), internal::priority_tag<2>())) { return internal::begin(std::forward(range), internal::priority_tag<2>()); } // Simplified implementation of C++20's std::ranges::end. // As opposed to std::ranges::end, this implementation does does not check // whether end() returns an iterator and does not inhibit ADL. // // The trailing return type and dispatch to the internal implementation is // necessary to be SFINAE friendly. // // Reference: - https://wg21.link/range.access.end template constexpr auto end(Range&& range) noexcept -> decltype(internal::end(std::forward(range), internal::priority_tag<2>())) { return internal::end(std::forward(range), internal::priority_tag<2>()); } // Implementation of C++20's std::ranges::iterator_t. // // Reference: https://wg21.link/ranges.syn#:~:text=iterator_t template using iterator_t = decltype(ranges::begin(std::declval())); // Implementation of C++20's std::ranges::range_value_t. // // Reference: https://wg21.link/ranges.syn#:~:text=range_value_t template using range_value_t = iter_value_t>; } // namespace ranges } // namespace base #endif // BASE_RANGES_RANGES_H_