123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- // 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 <array>
- #include <iterator>
- #include <type_traits>
- #include <utility>
- #include "base/template_util.h"
- namespace base {
- namespace internal {
- // Overload for C array.
- template <typename T, size_t N>
- 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 <typename T, size_t N>
- constexpr T* begin(std::array<T, N>& array, priority_tag<2> tag) {
- return const_cast<T*>(begin(const_cast<const std::array<T, N>&>(array), tag));
- }
- // Overload for const std::array. Required since std::array::begin is not
- // constexpr prior to C++17.
- template <typename T, size_t N>
- constexpr const T* begin(const std::array<T, N>& array, priority_tag<2>) {
- return N != 0 ? &array[0] : nullptr;
- }
- // Generic container overload.
- template <typename Range>
- constexpr auto begin(Range&& range, priority_tag<1>)
- -> decltype(std::forward<Range>(range).begin()) {
- return std::forward<Range>(range).begin();
- }
- // Overload for free begin() function.
- template <typename Range>
- constexpr auto begin(Range&& range, priority_tag<0>)
- -> decltype(begin(std::forward<Range>(range))) {
- return begin(std::forward<Range>(range));
- }
- // Overload for C array.
- template <typename T, size_t N>
- 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 <typename T, size_t N>
- constexpr T* end(std::array<T, N>& array, priority_tag<2> tag) {
- return const_cast<T*>(end(const_cast<const std::array<T, N>&>(array), tag));
- }
- // Overload for const std::array. Required since std::array::end is not
- // constexpr prior to C++17.
- template <typename T, size_t N>
- constexpr const T* end(const std::array<T, N>& array, priority_tag<2>) {
- return N != 0 ? (&array[0]) + N : nullptr;
- }
- // Generic container overload.
- template <typename Range>
- constexpr auto end(Range&& range, priority_tag<1>)
- -> decltype(std::forward<Range>(range).end()) {
- return std::forward<Range>(range).end();
- }
- // Overload for free end() function.
- template <typename Range>
- constexpr auto end(Range&& range, priority_tag<0>)
- -> decltype(end(std::forward<Range>(range))) {
- return end(std::forward<Range>(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 <typename Range>
- constexpr auto begin(Range&& range) noexcept
- -> decltype(internal::begin(std::forward<Range>(range),
- internal::priority_tag<2>())) {
- return internal::begin(std::forward<Range>(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 <typename Range>
- constexpr auto end(Range&& range) noexcept
- -> decltype(internal::end(std::forward<Range>(range),
- internal::priority_tag<2>())) {
- return internal::end(std::forward<Range>(range), internal::priority_tag<2>());
- }
- // Implementation of C++20's std::ranges::iterator_t.
- //
- // Reference: https://wg21.link/ranges.syn#:~:text=iterator_t
- template <typename Range>
- using iterator_t = decltype(ranges::begin(std::declval<Range&>()));
- // Implementation of C++20's std::ranges::range_value_t.
- //
- // Reference: https://wg21.link/ranges.syn#:~:text=range_value_t
- template <typename Range>
- using range_value_t = iter_value_t<iterator_t<Range>>;
- } // namespace ranges
- } // namespace base
- #endif // BASE_RANGES_RANGES_H_
|