1 | //===- llvm/ADT/ADL.h - Argument dependent lookup utilities -----*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLVM_ADT_ADL_H |
10 | #define LLVM_ADT_ADL_H |
11 | |
12 | #include <type_traits> |
13 | #include <iterator> |
14 | #include <utility> |
15 | |
16 | namespace llvm { |
17 | |
18 | // Only used by compiler if both template types are the same. Useful when |
19 | // using SFINAE to test for the existence of member functions. |
20 | template <typename T, T> struct SameType; |
21 | |
22 | namespace adl_detail { |
23 | |
24 | using std::begin; |
25 | |
26 | template <typename RangeT> |
27 | constexpr auto begin_impl(RangeT &&range) |
28 | -> decltype(begin(std::forward<RangeT>(range))) { |
29 | return begin(std::forward<RangeT>(range)); |
30 | } |
31 | |
32 | using std::end; |
33 | |
34 | template <typename RangeT> |
35 | constexpr auto end_impl(RangeT &&range) |
36 | -> decltype(end(std::forward<RangeT>(range))) { |
37 | return end(std::forward<RangeT>(range)); |
38 | } |
39 | |
40 | using std::rbegin; |
41 | |
42 | template <typename RangeT> |
43 | constexpr auto rbegin_impl(RangeT &&range) |
44 | -> decltype(rbegin(std::forward<RangeT>(range))) { |
45 | return rbegin(std::forward<RangeT>(range)); |
46 | } |
47 | |
48 | using std::rend; |
49 | |
50 | template <typename RangeT> |
51 | constexpr auto rend_impl(RangeT &&range) |
52 | -> decltype(rend(std::forward<RangeT>(range))) { |
53 | return rend(std::forward<RangeT>(range)); |
54 | } |
55 | |
56 | using std::swap; |
57 | |
58 | template <typename T> |
59 | constexpr void swap_impl(T &&lhs, |
60 | T &&rhs) noexcept(noexcept(swap(std::declval<T>(), |
61 | std::declval<T>()))) { |
62 | swap(std::forward<T>(lhs), std::forward<T>(rhs)); |
63 | } |
64 | |
65 | using std::size; |
66 | |
67 | template <typename RangeT> |
68 | constexpr auto size_impl(RangeT &&range) |
69 | -> decltype(size(std::forward<RangeT>(range))) { |
70 | return size(std::forward<RangeT>(range)); |
71 | } |
72 | |
73 | } // end namespace adl_detail |
74 | |
75 | /// Returns the begin iterator to \p range using `std::begin` and |
76 | /// function found through Argument-Dependent Lookup (ADL). |
77 | template <typename RangeT> |
78 | constexpr auto adl_begin(RangeT &&range) |
79 | -> decltype(adl_detail::begin_impl(std::forward<RangeT>(range))) { |
80 | return adl_detail::begin_impl(std::forward<RangeT>(range)); |
81 | } |
82 | |
83 | /// Returns the end iterator to \p range using `std::end` and |
84 | /// functions found through Argument-Dependent Lookup (ADL). |
85 | template <typename RangeT> |
86 | constexpr auto adl_end(RangeT &&range) |
87 | -> decltype(adl_detail::end_impl(std::forward<RangeT>(range))) { |
88 | return adl_detail::end_impl(std::forward<RangeT>(range)); |
89 | } |
90 | |
91 | /// Returns the reverse-begin iterator to \p range using `std::rbegin` and |
92 | /// function found through Argument-Dependent Lookup (ADL). |
93 | template <typename RangeT> |
94 | constexpr auto adl_rbegin(RangeT &&range) |
95 | -> decltype(adl_detail::rbegin_impl(std::forward<RangeT>(range))) { |
96 | return adl_detail::rbegin_impl(std::forward<RangeT>(range)); |
97 | } |
98 | |
99 | /// Returns the reverse-end iterator to \p range using `std::rend` and |
100 | /// functions found through Argument-Dependent Lookup (ADL). |
101 | template <typename RangeT> |
102 | constexpr auto adl_rend(RangeT &&range) |
103 | -> decltype(adl_detail::rend_impl(std::forward<RangeT>(range))) { |
104 | return adl_detail::rend_impl(std::forward<RangeT>(range)); |
105 | } |
106 | |
107 | /// Swaps \p lhs with \p rhs using `std::swap` and functions found through |
108 | /// Argument-Dependent Lookup (ADL). |
109 | template <typename T> |
110 | constexpr void adl_swap(T &&lhs, T &&rhs) noexcept( |
111 | noexcept(adl_detail::swap_impl(std::declval<T>(), std::declval<T>()))) { |
112 | adl_detail::swap_impl(std::forward<T>(lhs), std::forward<T>(rhs)); |
113 | } |
114 | |
115 | /// Returns the size of \p range using `std::size` and functions found through |
116 | /// Argument-Dependent Lookup (ADL). |
117 | template <typename RangeT> |
118 | constexpr auto adl_size(RangeT &&range) |
119 | -> decltype(adl_detail::size_impl(std::forward<RangeT>(range))) { |
120 | return adl_detail::size_impl(std::forward<RangeT>(range)); |
121 | } |
122 | |
123 | namespace detail { |
124 | |
125 | template <typename RangeT> |
126 | using IterOfRange = decltype(adl_begin(std::declval<RangeT &>())); |
127 | |
128 | template <typename RangeT> |
129 | using ValueOfRange = |
130 | std::remove_reference_t<decltype(*adl_begin(std::declval<RangeT &>()))>; |
131 | |
132 | } // namespace detail |
133 | } // namespace llvm |
134 | |
135 | #endif // LLVM_ADT_ADL_H |
136 | |