tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ranges.h (4587B)


      1 // Copyright 2020 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_RANGES_RANGES_H_
      6 #define BASE_RANGES_RANGES_H_
      7 
      8 #include <array>
      9 #include <iterator>
     10 #include <type_traits>
     11 #include <utility>
     12 
     13 #include "base/template_util.h"
     14 
     15 namespace base {
     16 
     17 namespace internal {
     18 
     19 // Overload for C array.
     20 template <typename T, size_t N>
     21 constexpr T* begin(T (&array)[N], priority_tag<2>) {
     22  return array;
     23 }
     24 
     25 // Overload for mutable std::array. Required since std::array::begin is not
     26 // constexpr prior to C++17. Needs to dispatch to the const overload since only
     27 // const operator[] is constexpr in C++14.
     28 template <typename T, size_t N>
     29 constexpr T* begin(std::array<T, N>& array, priority_tag<2> tag) {
     30  return const_cast<T*>(begin(const_cast<const std::array<T, N>&>(array), tag));
     31 }
     32 
     33 // Overload for const std::array. Required since std::array::begin is not
     34 // constexpr prior to C++17.
     35 template <typename T, size_t N>
     36 constexpr const T* begin(const std::array<T, N>& array, priority_tag<2>) {
     37  return N != 0 ? &array[0] : nullptr;
     38 }
     39 
     40 // Generic container overload.
     41 template <typename Range>
     42 constexpr auto begin(Range&& range, priority_tag<1>)
     43    -> decltype(std::forward<Range>(range).begin()) {
     44  return std::forward<Range>(range).begin();
     45 }
     46 
     47 // Overload for free begin() function.
     48 template <typename Range>
     49 constexpr auto begin(Range&& range, priority_tag<0>)
     50    -> decltype(begin(std::forward<Range>(range))) {
     51  return begin(std::forward<Range>(range));
     52 }
     53 
     54 // Overload for C array.
     55 template <typename T, size_t N>
     56 constexpr T* end(T (&array)[N], priority_tag<2>) {
     57  return array + N;
     58 }
     59 
     60 // Overload for mutable std::array. Required since std::array::end is not
     61 // constexpr prior to C++17. Needs to dispatch to the const overload since only
     62 // const operator[] is constexpr in C++14.
     63 template <typename T, size_t N>
     64 constexpr T* end(std::array<T, N>& array, priority_tag<2> tag) {
     65  return const_cast<T*>(end(const_cast<const std::array<T, N>&>(array), tag));
     66 }
     67 
     68 // Overload for const std::array. Required since std::array::end is not
     69 // constexpr prior to C++17.
     70 template <typename T, size_t N>
     71 constexpr const T* end(const std::array<T, N>& array, priority_tag<2>) {
     72  return N != 0 ? (&array[0]) + N : nullptr;
     73 }
     74 
     75 // Generic container overload.
     76 template <typename Range>
     77 constexpr auto end(Range&& range, priority_tag<1>)
     78    -> decltype(std::forward<Range>(range).end()) {
     79  return std::forward<Range>(range).end();
     80 }
     81 
     82 // Overload for free end() function.
     83 template <typename Range>
     84 constexpr auto end(Range&& range, priority_tag<0>)
     85    -> decltype(end(std::forward<Range>(range))) {
     86  return end(std::forward<Range>(range));
     87 }
     88 
     89 }  // namespace internal
     90 
     91 namespace ranges {
     92 
     93 // Simplified implementation of C++20's std::ranges::begin.
     94 // As opposed to std::ranges::begin, this implementation does does not check
     95 // whether begin() returns an iterator and does not inhibit ADL.
     96 //
     97 // The trailing return type and dispatch to the internal implementation is
     98 // necessary to be SFINAE friendly.
     99 //
    100 // Reference: https://wg21.link/range.access.begin
    101 template <typename Range>
    102 constexpr auto begin(Range&& range) noexcept
    103    -> decltype(internal::begin(std::forward<Range>(range),
    104                                internal::priority_tag<2>())) {
    105  return internal::begin(std::forward<Range>(range),
    106                         internal::priority_tag<2>());
    107 }
    108 
    109 // Simplified implementation of C++20's std::ranges::end.
    110 // As opposed to std::ranges::end, this implementation does does not check
    111 // whether end() returns an iterator and does not inhibit ADL.
    112 //
    113 // The trailing return type and dispatch to the internal implementation is
    114 // necessary to be SFINAE friendly.
    115 //
    116 // Reference: - https://wg21.link/range.access.end
    117 template <typename Range>
    118 constexpr auto end(Range&& range) noexcept
    119    -> decltype(internal::end(std::forward<Range>(range),
    120                              internal::priority_tag<2>())) {
    121  return internal::end(std::forward<Range>(range), internal::priority_tag<2>());
    122 }
    123 
    124 // Implementation of C++20's std::ranges::iterator_t.
    125 //
    126 // Reference: https://wg21.link/ranges.syn#:~:text=iterator_t
    127 template <typename Range>
    128 using iterator_t = decltype(ranges::begin(std::declval<Range&>()));
    129 
    130 // Implementation of C++20's std::ranges::range_value_t.
    131 //
    132 // Reference: https://wg21.link/ranges.syn#:~:text=range_value_t
    133 template <typename Range>
    134 using range_value_t = iter_value_t<iterator_t<Range>>;
    135 
    136 }  // namespace ranges
    137 
    138 }  // namespace base
    139 
    140 #endif  // BASE_RANGES_RANGES_H_